本次补充的模块,包括logging模块、hashlib模块、datetime模块、shutil模块、xml模块、subprocess模块、struct模块、colections模块,共计8个模块.
1.logging模块
''' 整体说明: 01 日志就是记录一些信息,方便查询或者辅助开发。 02 日志有两种形式,一种是记录到文件中,一种是显示屏幕(控制台)中。 03 日志有3个版本,低配版、标配版、高配版。 04 日志的5种等级,由低到高的顺序如下: (1)logging.debug('调试模式'),默认值为10 (2)logging.info('正常运行') ,默认值为20 (3)logging.warning('警告'),默认值为30 (4)logging.error('错误'),默认值为40 (5)logging.critical('系统崩了'),默认值为50 05 默认的日志级别设置为warning。 ''' # 低配版本:只能写入文件或者是屏幕显示。 import logging logging.basicConfig( # level= 10, level=logging.DEBUG, # 设置显示的级别 format='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s ', # 设置日志显示格式 datefmt="%Y-%m-%d", # 设置日期,与astime对应 filename='a.log', # 默认我a模式,使用的是gbk形式编码。 filemode="a" # 可以修改模式,但是一般不用修改 ) logging.debug("调试模式") logging.info("正常运行") logging.warning("警告") logging.error("错误") logging.critical("系统崩溃了") # 标配版本:既能在文件中写入,又在屏幕显示。 import logging # 创建logging对象 logger = logging.getLogger() # 创建文件对象 fh1 = logging.FileHandler("a1,log",encoding="utf8") # 一定要指定编码方式,否则程序会报错。 fh2 = logging.FileHandler("a2.log",encoding="utf8") # 创建屏幕对象 sh =logging.StreamHandler() # 定义显示格式 formater1 = logging.Formatter( fmt='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s', # fmt变量名是固定的。 datefmt= "%Y-%m-%d %H:%M:%S", ) formater2 = logging.Formatter( fmt='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s', # fmt变量名是固定的。 datefmt= "%Y-%m-%d %H:%M:%S", ) formater3 = logging.Formatter( fmt='%(asctime)s %(filename)s %(message)s', # fmt变量名是固定的。 datefmt= "%Y-%m-%d %H:%M:%S", ) # 给对象绑定格式 fh1.setFormatter(formater1) fh2.setFormatter(formater2) sh.setFormatter(formater3) # 给logger对象添加其他对象 logger.addHandler(fh1) logger.addHandler(fh2) logger.addHandler(sh) # 设置logger级别 logger.setLevel(30) sh.setLevel(40) fh1.setLevel(40) fh2.setLevel(50) logging.debug('调试模式') # 10 logging.info('正常运行') # 20 logging.warning('警告') # 30 logging.error('错误') # 40 logging.critical('系统崩了') # 50 # 高配版本:通过导入文件(导入字典的方式)写日志Django import os 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' # 定义日志输出格式 结束 # print(__file__) logfile_dir = os.path.dirname(os.path.abspath(__file__)) # log文件的目录 logfile_name = '高配版.log' # log文件名 # # 如果不存在定义的日志目录就创建一个 # if not os.path.isdir(logfile_dir): # os.mkdir(logfile_dir) # log文件的全路径 logfile_path = os.path.join(logfile_dir, logfile_name) # log配置字典 # 第一层键值对的键固定的关键字不能改变,即version、disable_existing_loggers、formatters、filters、handlers、loggers不能改变。 LOGGING_DIC = { 'version': 1, # 版本 'disable_existing_loggers': False, # 'formatters': { 'standard': { 'format': standard_format }, 'simple': { 'format': simple_format }, 'id_simple_format':{ 'format': id_simple_format } }, 'filters': {}, 'handlers': { #打印到终端的日志 'console': { 'level': 'ERROR', # 设置在终端显示的等级 'class': 'logging.StreamHandler', # 打印到屏幕 'formatter': 'simple' }, #打印到文件的日志,收集info及以上的日志 'default': { 'level': 'DEBUG', # 设置在文件打印的等级 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件 'formatter': 'standard', 'filename': logfile_path, # 日志文件 'maxBytes': 300, # 日志大小 300bytes 'backupCount': 5, # 最多只有5个文件 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了 }, }, 'loggers': { #logging.getLogger(__name__)拿到的logger配置 '': { 'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕 'level': 'DEBUG', 'propagate': True, # 向上(更高level的logger)传递 }, }, } logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置 # # logging.config # 将你写好的logging 字典 在导入logging.config后,传到logging模块中 logger = logging.getLogger() # 生成一个log实例 通过字典自己设置的个性化的log对象 logging.debug('调试模式') # 10 logging.info('正常运行') # 20 logging.warning('警告') # 30 logging.error('错误') # 40 logging.critical('系统崩了') # 50
2.hashlib模块
''' 整体说明: 01 hash:对不可变的数据(int bool str tuple)进行哈希算法,将数据str tuple转化成为等长度的一串数字。 02 python中的haslib提供了常见的摘要算法,如MD5、SHA1. 03 摘要算法:又称哈希算法、散列算法,它通过一个函数,把任意长度的数据转换成为一个长度固定的数据串(通常用16机制的字符串表示)。 04 摘要算法的作用:通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。摘要算法 之所以能指出数据是否被篡改过,就是因为摘要函数是一个单项函数,计算(data)很容易,但是通过摘要digest反对data却非常困难。而且,对 原始数据做一个bit的修改,都会导致计算出的摘要完全不同。 05 加密原则说明: (1)加密类型必须是str (2)无论这个str多长,加密之后都转化为成等长度的数字。 (3)无论在任何机器上,对相同的字符串进行加密,加密的密文一致。 (4)不同的字符串加密之后的密文一定不同。 06 hashlib的用途: (1)对密码进行加密 a)普通加密 b)加固定盐 c)动态加盐 (2)文件的校验 ''' # 01 hashlib的的简单举例 import hashlib ret = hashlib.md5() ret.update("马玉刚".encode("utf8")) print(ret.hexdigest()) # 02 hashlib的应用 # 0201 对密码进行加密 # md5加密 # a,普通加密 import hashlib def encryption(password): # 定义对password加密的函数 ret = hashlib.md5() ret.update(password.encode('utf-8')) return ret.hexdigest() def register(): username = input('>>>') password = input('>>>') password = encryption(password) # 引用加密函数,对密码进行加密 with open('register', encoding='utf-8', mode='a') as f1: f1.write('{}|{}'.format(username, password)) # 各式化写入文件、。 register() # b, 加固定盐。 ''' dsaflsak@123213OHJ123 #简单密码普遍存在: 123456 111111 666666 .... ''' import hashlib ret = hashlib.md5('马玉刚'.encode('utf-8')) ret.update('alex3714'.encode('utf-8')) print(ret.hexdigest()) # c 动态加盐。 import hashlib username = '马玉刚' password = '马玉刚123456' ret = hashlib.md5(username[::2].encode('utf-8')) # 动态加盐 ret.update('alex3714'.encode('utf-8')) print(ret.hexdigest()) # sha 加密 import hashlib ret = hashlib.sha1() ret.update('马玉刚'.encode('utf-8')) print(ret.hexdigest()) import hashlib ret = hashlib.sha512() ret.update('fdsklafdsjafklsdajflksdfjsadf'.encode('utf-8')) print(ret.hexdigest()) # 固定盐动态盐与上面一致。 # 2,文件的校验。 import hashlib s1 = '狗哥,好黑呀,现场怼呀' ret = hashlib.md5() ret.update(s1.encode('utf-8')) print(ret.hexdigest()) # 7bc77d0bc1281428e5c63e628fa40c49 ret = hashlib.md5() ret.update('狗哥'.encode('utf-8')) ret.update(',好黑呀'.encode('utf-8')) ret.update(',现场'.encode('utf-8')) ret.update('怼'.encode('utf-8')) ret.update('呀'.encode('utf-8')) print(ret.hexdigest()) # 7bc77d0bc1281428e5c63e628fa40c49 # 小文件:可以采用一次性全部读出 import hashlib def file_hashlib(file): ret = hashlib.md5() with open(file, mode='rb') as f1: ret.update(f1.read()) return ret.hexdigest() print(file_hashlib('文件校验1')) print(file_hashlib('文件校验2')) # 大文件:用for循环可以逐行读取大文件,避免读大文件导致程序崩溃。 import hashlib def file_hashlib(file): ret = hashlib.md5() with open(file, mode='rb') as f1: for i in f1: ret.update(i) return ret.hexdigest() print(file_hashlib('文件校验1')) print(file_hashlib('文件校验2'))
3.datetime模块
import datetime now_time = datetime.datetime.now() # 现在的时间 # 只能调整的字段:weeks days hours minutes seconds print(datetime.datetime.now() + datetime.timedelta(weeks=3)) # 三周后 print(datetime.datetime.now() + datetime.timedelta(weeks=-3)) # 三周前 print(datetime.datetime.now() + datetime.timedelta(days=-3)) # 三天前 print(datetime.datetime.now() + datetime.timedelta(days=3)) # 三天后 print(datetime.datetime.now() + datetime.timedelta(hours=5)) # 5小时后 print(datetime.datetime.now() + datetime.timedelta(hours=-5)) # 5小时前 print(datetime.datetime.now() + datetime.timedelta(minutes=-15)) # 15分钟前 print(datetime.datetime.now() + datetime.timedelta(minutes=15)) # 15分钟后 print(datetime.datetime.now() + datetime.timedelta(seconds=-70)) # 70秒前 print(datetime.datetime.now() + datetime.timedelta(seconds=70)) # 70秒后 current_time = datetime.datetime.now() # 可直接调整到指定的 年 月 日 时 分 秒 等 print(current_time.replace(year=1977)) # 直接调整到1977年 print(current_time.replace(month=1)) # 直接调整到1月份 print(current_time.replace(year=1989,month=4,day=25)) # 1989-04-25 18:49:05.898601 # 将时间戳转化成时间 print(datetime.date.fromtimestamp(1232132131)) # 2009-01-17
4.shutil模块
''' 整体说明: 01 高级的文件、文件夹、压缩包处理模块 ''' # 将文件内容拷贝到另一个文件中 import shutil shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w')) # 拷贝文件 shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在 # 仅拷贝权限。内容、组、用户均不变 shutil.copymode('f1.log', 'f2.log') #目标文件必须存在 # 仅拷贝状态的信息,包括:mode bits, atime, mtime, flags shutil.copystat('f1.log', 'f2.log') #目标文件必须存在 # 拷贝文件和权限 shutil.copy('f1.log', 'f2.log') # 拷贝文件和状态信息 shutil.copy2('f1.log', 'f2.log') # 递归的去拷贝文件夹 shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 # 递归的去删除文件 shutil.rmtree('folder1') # 递归的去移动文件,它类似mv命令,其实就是重命名。 shutil.move('folder1', 'folder3') # shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的 import zipfile # 压缩 z = zipfile.ZipFile('laxi.zip', 'w') z.write('a.log') z.write('data.data') z.close() # 解压 z = zipfile.ZipFile('laxi.zip', 'r') z.extractall(path='.') z.close() # zipfile压缩解压缩 import tarfile # 压缩 t=tarfile.open('/tmp/egon.tar','w') t.add('/test1/a.py',arcname='a.bak') t.add('/test1/b.py',arcname='b.bak') t.close() # 解压 t=tarfile.open('/tmp/egon.tar','r') t.extractall('/egon') t.close() # tarfile压缩解压缩
5.xml模块
''' XML模块整体说明: xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代, 大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。现在这种格式的文件比较少了,但是还是存在的所以大家 简单了解一下,以备不时之需。 ''' # 01 对XML的增删改查简单操作。 # 增删改查 # 在进行操作之前,都应该进行这两步: import xml.etree.ElementTree as ET tree = ET.parse('a.xml') # 形成树形结构 root = tree.getroot() # 得到树的根系 print(root) # 循环打印: for i in root: print(i) ''' 输出结果:' <Element 'country' at 0x00000196B51191D8> <Element 'country' at 0x00000196B5124B88> <Element 'country' at 0x00000196B5124D18> ''' # 所有的增删改查都是基于这个root根系去操作 # 查: # 1,全文搜索 year 将所有的year标签全部找 print(root.iter('year')) print([i for i in root.iter('year')]) # 2,只找第一个,找到就返回 print(root.find('country')) # 3,在root的子节点找,找所有的 print(root.findall('country')) # 练习 # 找到标签也可以找到标签相应的内容:tag,attrib,text # 1,找所有的rank标签,以及 attrib 和 text (这里利用列表推导式比较方便) print([i for i in root.iter('rank')]) ''' 输出结果: [<Element 'rank' at 0x000001367D0D49F8>, <Element 'rank' at 0x000001367D0D4BD8>, <Element 'rank' at 0x000001367D0D4D68>] ''' print([i.attrib for i in root.iter('rank')]) ''' 输出结果: [{'updated': 'yes'}, {'updated': 'yes'}, {'updated': 'yes'}] ''' print([i.text for i in root.iter('rank')]) # ['2', '5', '69'] # 2,找到第二个country的 neighbor标签以及他的属性 print([tag for tag in root.findall('country')][1].find('neighbor').attrib) ''' 输出结果: {'direction': 'N', 'name': 'Malaysia'} ''' # 增 append import xml.etree.ElementTree as ET tree = ET.parse('a.xml') # 形成树形结构 root = tree.getroot() # 得到树的根系 # 给 year 大于2010年的所有标签下面添加一个month标签,属性为name:month 内容为30days for country in root.findall('country'): for year in country.findall('year'): if int(year.text) > 2010: month = ET.Element('month') month.text = '30days' month.attrib = {'name': 'month'} country.append(month) tree.write('b.xml') # 改 import xml.etree.ElementTree as ET tree = ET.parse('a.xml') # 形成树形结构 root = tree.getroot() # 得到树的根系 # 对所有的year属性以及值进行修改 for node in root.iter('year'): new_year=int(node.text)+1 node.text=str(new_year) node.set('updated','yes') node.set('version','1.0') tree.write('test.xml') # 删 import xml.etree.ElementTree as ET tree = ET.parse('a.xml') # 形成树形结构 root = tree.getroot() # 得到树的根系 # 将 rank值大于50的country标签删除 for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml') # 02 自己创建一个XML文件 import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"}) age = ET.SubElement(name, "age", attrib={"checked": "no"}) sex = ET.SubElement(name, "sex") sex.text = '33' name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"}) age = ET.SubElement(name2, "age") age.text = '19' et = ET.ElementTree(new_xml) # 生成文档对象 et.write("test.xml", encoding="utf-8", xml_declaration=True) ET.dump(new_xml) # 打印生成的格式
6.subprocess模块
''' 整体说明: 01 subprocess模块是python从2.4版本开始引入的模块。主要用来取代 一些旧的模块方法,如os.system、os.spawn*、os.popen*、 commands.*等。subprocess通过子进程来执行外部指令,并通过input/output/error管道,获取子进程的执行的返回信息。 02 可以实现通过python进程执行外部命令(模拟调用cmd来输出结果) ''' import subprocess obj = subprocess.Popen('dir', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) ret = obj.stdout.read().decode('gbk') # 正确命令 ret1 = obj.stderr.read().decode('gbk') # 错误命令 print(ret) print(ret1) # shell: 命令解释器,相当于调用cmd 执行指定的命令。 # stdout:正确结果丢到管道中。 # stderr:错了丢到另一个管道中。 # windows操作系统的默认编码是gbk编码。
7.struct模块
''' 整体说明:该模块可以把一个类型,如数字,转成固定长度的bytes类型。 ''' import struct # 将一个数字转化成等长度的bytes类型。 ret = struct.pack('i', 183346) print(ret, type(ret), len(ret)) # 通过unpack反解回来 ret1 = struct.unpack('i',ret)[0] print(ret1, type(ret1), len(ret1)) # 但是通过struct 处理不能处理太大 ret = struct.pack('l', 4323241232132324) print(ret, type(ret), len(ret)) # 报错
8.colections模块
''' 整体说明: 在内置数据类型(dict、list、set、tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter、deque、defaultdict、namedtuple和OrderedDict等。 1.namedtuple: 生成可以使用名字来访问元素内容的tuple 2.deque: 双端队列,可以快速的从另外一侧追加和推出对象 3.Counter: 计数器,主要用来计数 4.OrderedDict: 有序字典 5.defaultdict: 带有默认值的字典 '''