常用模块

自定义模块:

  • 什么是模块:一个.py文件就是模块,节省代码,容易维护,组织结构更清晰

  • 模块的运行方式:

    • 脚本方式:直接用解释器执行,或者pycharm中右键运行。

    • 模块方式:被其他的模块导入,为导入他的模块提供资源(变量,函数定义,)

常用的模块:

  • json 不同语言之间序列化

  • pickle pyton语言使用,支持序列化数据类型多

  • sys 与python解释器交互的,解决变量路径问题

  • os 文件目录操作,操作系统底层函数

  • hashlib 加密模块

  • time 时间模块

  • datetime 时间模块,查找之前之后时间使用的较多

  • rendom 取随机值

  • logging 记录日志

  • collections 定义特殊的数据类型

  • re 正则

  • subprocess 执行windows端命令

模块的分类:

  • 内置模块:标准库,python解释器自带的,time,os,sys,等等200多种
  • 第三方库(模块):各种大神写的模块,通过pip install...安装的6000多种
  • 自己写的模块,自定义模块

引用模块发生三件事:

  • 1,import haiyang将haiyang.py文件(变量,函数名)加载到内存
  • 2,在内存中创建一个以haiyang命名的名称空间
  • 3,通过haiyang.xx名称空间的名字.等方式引用此模块的名字(变量,函数名)

引用多个模块:

  • import os
  • import sys #引用多个模块时,要逐行引用

import haiyang:

  • 当我引用haiyang模块的时候,实际上将haiyang.py执行一遍,加载到内存
    通过import引用的模块,他有自己的独立名称空间,与当前执行文件没有关系。
    
    执行文件:02 模块 import
    被引用文件(模块):haiyang.py
    为模块起别名:
    import  haiyang as ab
    print(ab.name)
    

from haiyang import *:

  • 示例1:被引用文件(模块)all进行限制引用者使用范围

  • 引用者:
    from haiyang import *
    
    模块:
    __all__ = ['name']
    name = "huhaiyang"
    
  • 工作中错误示例:

  • from haiyang import name:
    from haiyang import *
    相当于从haiyang模块的全局空间中将name变量与值得对应关系,复制到当前执行文件的全局空间中
    引用模块中的函数,如果此函数修改一些变量,这些变量还是从此模块中寻找,不会改变当前执行文件变量
    
    优点:调用更方便
    缺点:引用变量跟当前文件变量冲突
    

py文件的两种功能:

  • 1.py文件的第一个功能:执行文件(承载代码)脚本,直接打印`__name__`返回`__main__`
    
    2.py文件的第二个功能:模块(被动执行文件),直接打印`__name__`返回模块名
    
    作用:当你在被执行文件中,引用模块后,返回的是模块名,模块中进行了`if __name__ == '__main__':`
    判断的话,被执行者是不会执行此函数(控制函数自动调用),模块中可以进行测试代码    
    

寻找一个模块的路径:

  • 内存中 >>> 内置模块 >>> sys.path
  • 只要这三个地方存在,就可以进行加载这个模块

不同目录加载模块;

  • 将路径加载到sys.path中,以绝对路径导入。

  • import sys
    sys.path.append(r'E:\Python-学习\')
    import haiyang
    
    print(haiyang.name)
    

包的使用:

  • 一个文件其实就是有个包

  • 创建一个包 new-package,会自行创建一个·__init__文件·

  • 创建包过程:

    • 1.将该aaa包内__init__.py文件加载到内存

    • 2.创建一个以aaa,命名的名称空间

    • 3.通过aaa. 的方式引用__init__的所有名字

  • 首先,无论在哪里引用模块,import或者from .. import..

  • 最开始的模块或者包的内存,每只sys,path中能找到的

  • 直接import 为了让我们会使用包里面的__init__

  • import 导入包以及包内的功能:

    • 示例1:简单的包引用

    • bolg
      |____ aaa
      |    |__ __init__.py   #from aaa import m1
      |    |__ m1.py         #定义函数func
      |
      |____ run.py         #aaa.m1.func()
      
      aaa目录文件m1 定义func函数:
      aaa目录__init__文件中定义:from aaa import m1
      
      import aaa
      #1.在执行文件写入import aaa
      #2.aaa的__init__里面写入 from aaa import m1
      #3.然后执行aaa.m1.a
      
      aaa.m1.func()
      
    • 示例2:多层目录引用__init__

    • #在当前文件中,引用aaa包下的bbb包的变量name
      #1.在执行文件写入import aaa
      #2.aaa的__init__里面写入 from aaa import bbb
      #3.bbb的__init__里面写入一个变量 name ="海洋"
      #4.然后执行aaa.bbb
      
      import aaa
      print(aaa.bbb.name)
      
    • 示例3:多层目录引用变量

    • bolg
      |____aaa
      |    |__bbb
      |    |  |__ __init__.py   #相对from ..bbb import m3 或者 from .mb import func3
      |    |  |__ m3.py         #func3函数
      |    | 
      |    |__ __init__.py      #from aaa import bbb/from aaa import m1
      |    |__ m1.py            #func1函数
      |    |__ m2.py
      |
      |____ run.py
      
      #在当前文件中,引用aaa包目录下的bbb包的变量name
      #1.在执行文件写入import aaa
      #2.在aaa的__init__里面写入 from aaa import bbb (bbb包里面的__init__里面可以引用)
      #3.在bbb包的__init__写入 from  aaa.bbb import m3
      #4.然后执行aaa.bbb.m3.func3()
      
      import aaa.bbb
      aaa.bbb.m3.func3()  #调用aaa下bbb下m3
      aaa.bbb.func3()     #init直接引用func3函数时不用加mb
      aaa.m1.func1()      #调用aaa目录下的m1
      
  • from ... import .... 导入包以及包内的功能

    • 这种方式不用设置__init__文件

    • # from a.b.c import d.e.f
      # c的前面必须是个包
      # import 的后面一定是名字,并且不能再有点
      
      #第一种直接引用目录文件下的变量
      from  aaa.bbb.m2 import  func1
      func1()
      
      #第二种直接引用目录下的文件
      from aaa.bbb import m2
      m2.func1()
      
      

  • 模块划整一个包:

    • # 由于nb模块增加了很多很多功能,所以我们nb这个文件就要划整一个包,
      # 无论对nb模块有任何操作,对于使用者来说不应该改变,极少的改变对其的调用.
      bolg
      |____ nb
      |    |__ __init__.py 
      |    |__ m1.py        #函数f1,f2
      |    |__ m2.py       #函数f3
      |
      |____ run.py
      
      __init__.py存放:
      from nb.m1 import f1,f2
      from nb.m2 import f3
      
      执行文件:
      run.py  执行:nb.f1() nb.f2() nb.f3()
      
      
  • 多层目录引用:

    • bolg         #第一层
      |____NB      #第二层
      |    |__dsb  #第三层
      |    |    |__ly       #f3
      |    |__ __init__.py  
      |    |__ m1.py        #f1函数 
      |    |__ m2.py        #f2函数
      |
      |____ run.py
      
      #__init__存放
      from .m1 import f1
      from .m2 import f2
      from .dsb.ly import f3
      
      #执行文件:
      #第一种运行方法,将目录添加到sys.path
      # import sys
      # sys.path.append(r'E:\相对导入绝对导入\bolg')
      import NB as nb
      nb.f1()
      nb.f2()
      nb.f3
      
      #第二种运行方法:
      import dir.NB as nb
      nb.f1()
      nb.f2()
      nb.f3()
      
      

模块使用:

序列化模块:

  • 序列化模块:将一种数据结构 (list,dict) 转化成一个特殊的序列(特殊的字符串,bytes)的过程

    ​ 并且还可以翻转回去。

  • 为什么要有序列化:

    • str(list)字符串存储到文件中,读取出来,反转不回去
    • 凡是数据通过网络传出去最终格式必须是bytes类型
  • json模块:

  • 支持python数据结构有限:int str list dict tuple bool none float

  • pickle模块:

    • 支持python中所有的数据类型以及对象,只能是python语言中使用的
  • shevle模块:

    • 只能是文件存取

json模块方法:

  • dumps序列化: loads 反序列化(主要用于网络传输和多文件存取)

  • import json
    dic = {'username':'海洋'}
    ret = json.dumps(dic)
    print(ret)
    
    ret1 = json.loads(ret)
    print(ret1)
    
    特殊参数
    import json
    dic = {'username': '海洋', 'password': 123,'status': False}
    ret = json.dumps(dic,ensure_ascii=False,sort_keys=True)
    ret1 = json.loads(ret)
    
    print(ret,type(ret))
    print(ret,type(ret1))
    
    #文件存取:
    import json
    dic = {'username': '海洋', 'password': 123,'status': False}
    
    with open("jsontest",encoding='utf-8',mode='w') as f1:
         ret = json.dumps(dic)
         f1.write(ret)
    
    with open("jsontest", encoding='utf-8') as f1:
        ret2 = json.loads(f1.read())
        print(ret2)
    
    
  • 多个文件存储使用dumps:

  • import json
    dic1 = {'username': '海洋', 'password': 123,'status': False}
    dic2 = {'username': '俊丽', 'password': 123,'status': False}
    dic3 = {'username': '宝宝', 'password': 123,'status': False}
    
    with open("jsontest",encoding='utf-8',mode='a') as f1:
         f1.write(f"{json.dumps(dic1)}\n{json.dumps(dic2)}\n{json.dumps(dic3)}\n")
    
    with open("jsontest", encoding='utf-8') as f1:
        for line in f1:
            ret = json.loads(line)
            print(ret,type(ret))
    
    
  • dump load:只能用于单个数据的存储文件(不常用 )

  • #不需要先转换字符串,节省一些代码
    import json
    dic = {'username': '海洋', 'password': 123,'status': False}
    
    with open("jsontest",encoding='utf-8',mode='w') as f1:
         json.dump(dic,f1)
    
    with open("jsontest", encoding='utf-8') as f1:
        dic1 = json.load(f1)
        print(dic1)
    

pickle模块:

  • dumps,loads:(只能是网络传输)

  • import pickle
    l1 = ["海洋",'俊丽',888]
    
    l2 = pickle.dumps(l1)
    l3 = pickle.loads(l2)
    print(l2)
    print(l3)
    
  • dump load:(只能数据结构存取文件)

  • import pickle
    l1 = ["海洋",'俊丽',888]
    
    with open("jsontest",mode='wb') as f1:
        pickle.dump(l1,f1)
    
    with open("jsontest",mode='rb') as f2:
        ret = pickle.load(f2)
        print(ret,type(ret))
    
  • dump load:(pickle 多个文件写入)

  • import pickle
    l1 = ["海洋",'俊丽',888]
    l2 = ["海洋",'俊丽',888]
    l3 = ["海洋",'俊丽',888]
    
    with open("jsontest",mode='wb') as f1:
        pickle.dump(l1,f1)
        pickle.dump(l2,f1)
        pickle.dump(l3,f1)
    
    with open("jsontest",mode='rb') as f2:
        ret1 = pickle.load(f2)
        ret2 = pickle.load(f2)
        ret3 = pickle.load(f2)
        print(ret1,ret2,ret3,type(ret1))
    
  • pickle 对象写入文件:

  • #写入
    with open(settings.register_student,mode="ab") as f3:
         pickle.dump(obj_write,f3)
    #读取
    with open(settings.register_student,mode="rb") as f4:
          while 1:
               try:
                   ret1 = pickle.load(f4)
                    yield ret1
               except Exception:
                    break
    
    

sys模块:(路径)

  • import sys
    print(sys.path)      #获取当前路径
    print(sys.version)   #获取python版本
    1
    for i in range(3):
        print(i)
    sys.exit() #主动退出
    exit()  
    print(111)
    
    sys.path.append(路径)  #与python解释器进行交互,解决变量路径问题
    

os模块:(文件,目录)

  • 工作目录:当前目录,父级目录(上层目录)

  • #操作系统底层函数的方法
    import os
    # 查看当前工作目录和切换目录
    print(os.getcwd())
    print(os.chdir("路径"))  #切换目录,相当于shell的cd
    print(os.curdir)        #返回当前目录名
    print(os.pardir)        #返回当前目录的父目录字符串名
    
    
    # 和文件夹相关
    os.makedirs("haiyang/haha")     #在当前目录生成目录可以生成多层,类似mkdir -p
    os.removedirs('目录')            #若目录为为空则删除,不为空删除不了
    os.mkdir('目录')                 #生成单级目录
    os.rmdir('目录')                 #删除单级空目录,为空无法删除
    print(os.listdir('haiyang'))    #列出指定目录下的所有文件和子目录,以列表的方式
    
    
    # 和文件相关
    os.remove("file")               #删除文件
    os.rename('旧文件','新文件')      #重命名文件
    print(os.stat('jsontest'))      #获取文件/目录信息
    
    
    # path和路径相关
    # print(os.path.abspath('jsontest'))   #返回当前的绝对路径
    
    #将当前的绝对路径转化为列表,前面为路径,后面为文件名
    # print(os.path.split(os.path.abspath('jsontest')))  
    # print(__file__)    #动态获取当前文件的绝对路径
    
    # 获取当前文件的爷爷级目录
    # print(os.path.dirname(os.path.abspath('jsontest')))   #获取父级目录
    # print(os.path.basename(os.path.abspath('jsontest')))   #返回一个路径最后的文件名
    
    
    # 判断路径
    # os.path.join("路径1",'路径2')   #将多个路径拼接组合
    # print(os.path.isfile(os.path.abspath('jsontest')))  #判断路径是否是文件  在返回True
    # print(os.path.isdir(os.path.abspath('jsontest')))   #判断路径是否目录  在返回True
    # print(os.path.exists(os.path.abspath('jsontest')))  #判断当前路径是否存在  在返回True
    # print(os.path.isabs(os.path.abspath('jsontest')))   #判断是否是绝对路径   在返回True
    
    
    # print(os.path.getatime('文件或者目录'))               #查看文件或者目录最后访问时间
    # print(os.path.getmtime('文件或者目录'))               #查看文件或者目录最后修改时间
    # print(os.path.getsize("文件或者目录"))                #查看文件或者目录大小
    
    

hashlib模块:(加密)

  • 加密模块,摘要算法,散列算法,等等

  • 加密过程:

    • 1,将一个bytes类型的数据,通过hashlib进行加密返回,一个等长度的16进制数字
    • 2,过程不可逆
    • 3,相同的bytes类型的数据通过相同的加密方法得到的数据绝对相同
    • 4,不相同的bytes类型的数据通过相同的加密方法得到的数据也绝对不相同
  • 加密示例:

    • import hashlib
      ret = hashlib.md5()
      ret.update('海洋'.encode('utf-8'))
      print(ret.hexdigest())
      
      
  • 加盐示例:

    • import hashlib
      ret = hashlib.md5("俊丽".encode('utf-8'))   #俊丽盐
      ret.update('海洋'.encode('utf-8'))
      print(ret.hexdigest())
      
      
  • 动态加盐示例:

    • import hashlib
      username = input("输入用户名:").strip()
      password = input('输入密码').strip()
      ret = hashlib.md5(username.encode('utf-8'))   #动态的用户名
      ret.update('海洋'.encode('utf-8'))
      print(ret.hexdigest())
      
      
  • sha系列加密:

    • #sha系列:安全系数高,耗时高
      import hashlib
      username = input("输入用户名:").strip()
      password = input('输入密码').strip()
      ret = hashlib.sha3_512(username.encode('utf-8'))
      ret.update('海洋'.encode('utf-8'))
      print(ret.hexdigest())
      
      
  • 文件校验:

    • import hashlib
      def md5_file(path):
          ret = hashlib.md5()
          with open(path,mode='rb') as f1:
              while 1:
                  content = f1.read(1024)   #每次读取文件
                  if content:
                      ret.update(content)
                  else:
                      return ret.hexdigest()
      
      print(md5_file('python-3.7.4rc1-embed-win32.zip'))
      
      

time模块:(时间)

  • 三种形式:

    • 1,时间戳:time.time() 格林威治时间,时差,计时 1561696705.6334207
    • 2,人类看的懂的时间,格式化时间, 2019-6-28 12:00
    • 3,结构化时间:python语言使用的,解释器使用的 time.struct_time(tm_year=2019, .....
  • 格式化时间:

    • #%Y年 %m月 %d日  %H时  %M分 %S秒
      
      print(time.strftime("%Y-%m-%d %H:%M:%S" ))     #字符串类型的格式化时间
      print(time.strftime("%Y-%m-%d %H:%M:%S %A" ))  #字符串类型的格式化时间
      
      
  • 时间戳转换格式化时间

    • timetamp = time.time()
      st = time.localtime(timetamp)
      # print(st)
      time1 = time.strftime('%Y/%m/%d %H:%M:%S',st)
      print(time1)
      
      
  • 格式化时间转化成时间戳

    • import time
      ft = time.strftime('%y/%m/%d %H:%M:%S')
      # print(ft)
      st = time.strptime(ft,'%y/%m/%d %H:%M:%S')
      timestamp = time.mktime(st)
      print(timestamp)
      
      

datetime模块:

  • 查找之前的时间:

    • import datetime
      time1 = datetime.datetime.now()        #现在的时间
      print(datetime.datetime.now() + datetime.timedelta(weeks=3))  #三周前
      
      print(current_time.replace(year=1977))   #调整到指定年月
      
      
  • 将时间戳转化成时间:

    • print(datetime.date.fromtimestamp(1232132131))
      
      

random模块:

  • 随机取值

    • import random
      #随机字符串随机发红包时使用
      print(random.random())           #大于0小于1之间的小数
      print(random.uniform(1,6))       #随机取1-6的小数
      print(random.randint(1,5))       #1-5随机取值
      print(random.randrange(1,10,2))  #顾头不顾尾
      
      print(random.choice(['海洋','俊丽','宝宝']))  #可迭代对象随机取列表值
      print(random.sample(['海洋','俊丽','宝宝'],2)) #可迭代对象随机取列表值,2选两个
      
      item = [i for i in range(10)]   #原列表打乱顺序
      random.shuffle(item)
      print(item)
      
      

logging模块:

  • 系统日志:记录服务器的一些重要信息,监控系统,网卡流量,记录操作信息等等。
  • 网站日志:访问异常,卡顿,网站一些板块,受欢迎程度,访问量,点击率,等等。
  • 错误日志:开发人员在开发项目中利用日志进行排错,排除一些避免不了的错误,辅助开发
  • 记录用户信息日志:用户的消费习惯,新闻偏好等等(数据库解决)

  • 三个版本:
    • 1.low版 (简易版)
    • 2.标配版(标配版)
    • 3.旗舰版(项目中使用的,Django项目)

  • low版:

    • #缺点:文件与屏幕输出只能选择一个
      
      import logging
      logging.basicConfig(                   #设置级别才会出现info和debug
          # level=logging.DEBUG,
          level=30,                          #设置日志级别,可以调整
          format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', #日志格式
          filename=r'test.log',            #写入日志
      )
      logging.debug('调试模式')         #调试
      logging.info('信息信息')          #信息
      logging.warning('警告信息')       #警告
      logging.error('错误信息')         #错误
      logging.critical('严重错误')      #关键
      
      
  • 标配版:

    • #文件和屏幕都可以输入
      import logging
      
      logger = logging.getLogger()                                #创建一个logger对象
      fh = logging.FileHandler('标配版.log',encoding='utf-8')      #创建文件对象
      sh = logging.StreamHandler()                                #创建屏幕对象
      
      #创建显示格式:
      formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
      fh.setFormatter(formatter)       #绑定显示格式
      sh.setFormatter(formatter)
      
      logger.addHandler(fh)            #logger对象添加多个fh,ch对象
      logger.addHandler(sh)
      
      # logger.setLevel(10)            #总开关,不写默认级别30,先写总开关
      # fh.setLevel(30)
      # sh.setLevel(10)
      
      logging.debug('调试模式')         #调试
      logging.info('信息信息')          #信息
      logging.warning('警告信息')       #警告
      logging.error('错误信息')         #错误
      logging.critical('严重错误')      #关键
      
      
  • 旗舰版:

    • 自定制(通过字典的方式)日志

    • 轮转日志的功能

    • import logging.config    #引用配置文件/模块
      
      # 定义三种日志输出格式 开始
      standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                        '[%(levelname)s][%(message)s]'   #其中name为getlogger指定的名字
      simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
      id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'   #级别/时间/信息
      # 定义日志输出格式 结束
      
      
      #写入日志路径和日志名称
      logfile_name = 'log1.log'
      logfile_path = r"E:\Python-学习\作业\23期\day19-包的导入-login日志\日志\log1.log"
      
      
      # log配置字典
      #LOGGING_DIC第一层key不能改变
      LOGGING_DIC = {
          'version': 1,                                 #版本号
          'disable_existing_loggers': False,            #固定写法
          'formatters': {                               #日志格式
              'standard': {                             #标准格式
                  'format': standard_format
              },
              'simple': {                               #简单格式
                  'format': simple_format
              },
          },
          'filters': {},                                #过滤
          'handlers': {
              #打印到终端的日志
              'sh1': {                                  #终端日志打印到屏幕
                  'level': 'DEBUG',                     #debug开始打印
                  'class': 'logging.StreamHandler',
                  'formatter': 'simple'
              },
              #打印到文件的日志,收集info及以上的日志
              'staff_fh': {                                              #写到文件信息
                  'level': 'DEBUG',
                  'class': 'logging.handlers.RotatingFileHandler',       # 保存到文件
                  'formatter': 'standard',                               # 选择复杂的格式
                  'filename': logfile_path,                              # 日志文件
                  'maxBytes': 3000,        # 日志大小字节 5M1024*1024*5
                  'backupCount': 5,
                  'encoding': 'utf-8',     # 日志文件的编码,再也不用担心中文log乱码了
              },
              'boss': {  # 写到文件信息
                  'level': 'DEBUG',
                  'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
                  'formatter': 'standard',                          # 选择复杂的格式
                  'filename': logfile_path,                         # 日志文件
                  'maxBytes': 3000,  # 日志大小字节 5M1024*1024*5
                  'backupCount': 5,
                  'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
              },
          },   #句柄
          'loggers': {
              #logging.getLogger(__name__)拿到的logger配置
              '': {
                  'handlers': ['staff_fh', 'sh1','boss'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
                  'level': 'DEBUG',
                  'propagate': True,        # 向上(更高level的logger)传递
              },
          },                 #产生几个log
      }
      
      
      def load_my_logging_cfg(task_id):
          logging.config.dictConfig(LOGGING_DIC)    #通过你写的字典方式配置日志/第一步
          logger = logging.getLogger(task_id)       # 生成一个log实例/
          return logger
      
      def login():
          logging1 = load_my_logging_cfg("登录功能")
          logging1.info("海洋登录信息")
      
      def transfer():
          logging2 = load_my_logging_cfg("转账功能")
          logging2.info("张三给李四转账成功")
      
      login()
      transfer()
      
      
  • 旗舰版日志(函数):

    • import logging.config  
      def student_log(info,task_id):
          standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
                            '[%(levelname)s][%(message)s]'
          simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
      
          logfile_name = "student_info.log"
          logfile_path = os.path.join(settings.register_logs,logfile_name)
      
          LOGGING_DIC = {
              'version': 1,
              'disable_existing_loggers': False,
              'formatters': {
                  'standard': {
                      'format': standard_format
                  },
                  'simple': {
                      'format': simple_format
                  },
              },
              'filters': {},
              'handlers': {
                  'staff_fh': {
                      'level': 'DEBUG',
                      'class': 'logging.handlers.RotatingFileHandler',
                      'formatter': 'standard',
                      'filename': logfile_path,
                      'maxBytes': 3000000,
                      'backupCount': 5,
                      'encoding': 'utf-8',
                  },
              },   #句柄
              'loggers': {
                  '': {
                      'handlers': ['staff_fh'],
                      'level': 'DEBUG',
                      'propagate': True,
                  },
              },
          }
      
          logging.config.dictConfig(LOGGING_DIC)   #字典的配置信息
          logger = logging.getLogger(task_id)      #生成一个log实例
          logger.info(info)                        
          
      common.student_log(f"{self.name}创建了课程{ke_name}","创建课程功能") #调用日志
      
      

collections模块:

  • 给我们提供一下python数据类型,比较特殊的数据类型,出奇制胜

  • 1.namedtuple: 生成可以使用名字来访问元素内容的tuple(自定义类型)

    • #命名元祖
      from collections import namedtuple
      Point = namedtuple("point",['x','y'])  #"point" 自定义类型
      print(type(Point))
      p = Point(1,2)         #键值对存储
      print(type(p))
      print(p)
      print(p[0])		       #索引取值
      
      
  • 2.deque: 双端队列,类似于列表的一种容器性数据,插入元素,删除元素,效率高

    • from collections import deque
      #从后面添加
      q = deque(['a',1,'c','d'])
      q.append('e')
      print(q)
      
      #在前面添加
      q.appendleft("66")
      q.appendleft("77")
      q.pop()       #默认删除最后一个
      q.popleft()   #默认删除最前面的
      print(q)
      
      #按照索引删
      def q[2]
      print(q)
      
      
  • 3.Counter: 计数器,主要用来计数

    • from collections import  Counter
      
      c = Counter("sdagdjashdaskd")
      print(c)
      
      
  • 4.OrderedDict: 有序字典

    • from collections import OrderedDict
      od = OrderedDict()
      od['z'] = 1
      od['y'] = 2
      od['x'] = 3
      print(od.keys())
      
      
  • 5.defaultdict 带有默认值的字典

    • from  collections import defaultdict
      #not in方式
      l1 = [11,22,33,44,55,77,88,99]
      dic = {}
      for i in l1:
          if i < 66:
              if "key1" not in dic:
                  dic['key1'] = []
              dic['key1'].append(i)
          else:
              if 'key2' not in dic:
                  dic['key2'] = []
              dic['key2'].append(i)
      print(dic)
      
      #defaultdict方式
      l1 = [11,22,33,44,55,77,88,99]
      dic = defaultdict(list)
      for i in l1:
          if i < 66:
              dic['key1'].append(i)
          else:
              dic['key2'].append(i)
      print(dic)
      
      

re模块:

  • 正则表达式:从字符串中找出你想要的字符串

    • 在于对你想要得找个字符串进行一个精确的描述
    • 使用在爬虫中
  • 单个字符匹配:
    • #\W与w
      #\w 数字字母下划线中文
      #\W 非数字字母下划线中文
      print(re.findall("\w",'海洋jx 12*() _'))  #['海', '洋', 'j', 'x', '1', '2', '_']
      print(re.findall("\W",'海洋jx 12*() _'))  #[' ', '*', '(', ')', ' ']
      
      #\s 空格 换行符
      #\S 非空格 换行符
      print(re.findall('\s','海洋haiyang*(_ \t \n'))  #[' ', '\t', ' ', '\n']
      print(re.findall('\S','海洋haiyang*(_ \t \n'))  #['海', '洋', 'h', 'a'.....
      
      #\d  匹配数字 \d\d匹配两个字符
      #\D  匹配非数字 \d\d匹配两个字符
      print(re.findall('\d','12345 hai*(_'))  #['1', '2', '3', '4', '5']
      print(re.findall('\D','12345 hai*(_'))  #[' ', 'h', 'a', 'i'.....
      
      #\A  匹配以什么开头
      # ^
      print(re.findall('\Ahello','hello 胡海洋 -_- 666'))    #['hello']
      print(re.findall('^hello','hello 胡海洋 -_- 666'))     #['hello']
      
      # \Z、\$ 匹配以什么结尾
      print(re.findall('666\Z','hello 海洋 *-_-* \n666'))   #['666']
      print(re.findall('666$','hello 海洋 *-_-* \n666'))    #['666']
      
      # \n 与 \t 匹配\n 与 \t
      print(re.findall('\n','hello \n 海洋 \t*-_-*\t \n666'))  # ['\n', '\n']
      print(re.findall('\t','hello \n 海洋 \t*-_-*\t \n666'))  # ['\t', '\t']
      
      
  • 元字符匹配:
    • #. ? * + {m,n} . * .*?
      #. 匹配任意字符
      #如果匹配成功,光标则移动到下一位
      #如果为匹配成功,光标向下移动一位
      print(re.findall('a.b', 'aabbb,ab aab a*b aaab a海b')) ['aab', 'aab',....
                                                             
      #? 匹配0个或者1个 由左边字符定义的片段,不是ab 就是b(不匹配a)
      print(re.findall('a?b', 'aabbb,ab aab a*b aabb a海b' ))
                                                             
      # * 匹配0个或者多个左边字符表达式。 满足贪婪匹配 
      print(re.findall('a*b', 'ab aab aaab abbb'))
      print(re.findall('ab*', 'ab aab aaab abbbbb'))            
                                                             
      # + 匹配1个或者多个左边字符表达式。 满足贪婪匹配 
      print(re.findall('a+b', 'ab aab aaab abbb'))  # ['ab', 'aab', 'aaab', 'ab']       
      
      # {m,n}  匹配m个至n(n能取到)个左边字符表达式。 满足贪婪匹配
      print(re.findall('a{2,4}b', 'ab aab aaab aaaaabb'))  # ['aab', 'aaab']
                                             
      
      
  • 贪婪匹配:
    • #.*  贪婪匹配 从头到尾,必须要a开头b结尾,中间全部匹配,贪婪匹配
      #.换行符不匹配
      print(re.findall('a.*b', 'ab aab a*()b'))  # ['ab aab a*()b']
      #换行符也可以匹配
      print(re.findall('a.*b', 'ab aab a*()b',re.DOTALL))  # ['ab aab a*()b']
      
      
  • 非贪婪匹配:
    • # .*? 此时的?不是对左边的字符进行0次或者1次的匹配,
      # 而只是针对.*这种贪婪匹配的模式进行一种限定:告知他要遵从非贪婪匹配 推荐使用!
      # a到b就匹配也就是0个或者多个
      print(re.findall('a.*?b', 'ab a1b a*()b, aaaaaab'))  # ['ab', 'a1b', 'a*()b']
      
      # []: 括号中可以放任意一个字符,一个中括号代表一个字符
      print(re.findall('[ab]', 'a1b a3b aeb a*b arb a_b'))             #匹配里面的a或者b
      print(re.findall('a[abc]b', 'aab abb acb adb afb a_b'))          #匹配前后加[]里面一个
      print(re.findall('a[0-9]b', 'a1b a3b aeb a*b arb a_b'))           #数字
      print(re.findall('a[a-z]b', 'a1b a3b aeb a*b arb a_b'))           #小写
      print(re.findall('a[a-zA-Z]b', 'aAb aWb aeb a*b arb a_b'))        #大小写
      print(re.findall('a[0-9][0-9]b', 'a11b a12b a34b a*b arb a_b'))  #符合a[][]b里面的两个数字
      print(re.findall('a[*-+]b','a-b a*b a+b a/b a6b'))                #取符号
      
      #当你想匹配- 时,要把他放在[]里面的最前面
      print(re.findall('a[-*$]b','a-b a$b a*b'))
      
      #^ 在[]中表示取反的意思.
      print(re.findall('a[^0-9]b', 'a1b a3b aeb a*b arb a_b'))
      
      
      
  • 分组:
    • #()分组取
      s = 'haiyang_sb junli_sb baobao_sb haha_nb xixi_sb dd_sb'
      print(re.findall('(\w+)_sb',s))
      
      #|匹配左边或者右边
      print(re.findall('haiyang|junli', 'haiyangjunli'))
      
      
      #先把分组去掉筛选,在返回ies和y
      print(re.findall('compan(y|ies)',
                       'Too many companies have gone bankrupt, and the next one is my company'))
      
      #(?):将全部的内容返回,而不是将组内的内容返回,companies|company道理一样
      print(re.findall('compan(?:y|ies)',
                       'Too many companies have gone bankrupt, and the next one is my company'))
      
      
      
      
  • re常用方法:
    • findall 全部找到以列表返回

    • print(re.findall('a', 'alexwusirbarryeval'))  # ['a', 'a', 'a']
      
      

    • search 找到第一个符合条件的字符串就返回,通过.group()返回

    • print(re.search('sb|alex', 'alex sb sb barry 日天'))
      print(re.search('alex', 'alex sb sb barry 日天').group())
      
      

    • match:None,从字符串开头匹配,如果第一个条件字符串符合规则则返回,否则返回none

    • print(re.match('barry', 'barry alex wusir 日天'))
      print(re.match('barry', 'barry alex wusir 日天').group())
      
      
    • split 分割 可按照任意分割符进行分割:

    • print(re.split('[ ::,;;,]','alex wusir,日天,太白;女神;肖锋:吴超'))
      
      
    • sub 替换:

    • print(re.sub('俊丽', '海洋', '俊丽是最好的'))
      
      
    • 自定义obj:

    • obj=re.compile('\d{2}')
      
      print(obj.search('abc123eeee').group())  #12
      print(obj.findall('abc123eeee'))         #['12'],重用了obj自定义obj:
      
      
    • finditer 迭代器返回

    • ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
      print(ret)                               # <callable_iterator object at 0x10195f940>
      print(next(ret).group())                 #查看第一个结果
      print(next(ret).group())                 #查看第二个结果
      print([i.group() for i in ret])         #查看剩余的左右结果
      

subprocess:

  • 调用示例:

    • #dir为调用的命令
      import subprocess
      
      obj = subprocess.Popen('dir',
                             shell=True,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             )
      
      print(obj.stdout.read().decode('gbk'))  # 正确命令
      print('error:',obj.stderr.read().decode('gbk'))  # 错误命令
      
posted @ 2019-06-26 17:58  海洋1994  阅读(1151)  评论(0编辑  收藏  举报