• 模块补充


    本次补充的模块,包括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: 带有默认值的字典
    '''
  • 相关阅读:
    spring的@Transactional注解详细用法
    解决:No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency
    SpringBoot2 启动报错 Failed to auto-configure a DataSource
    SpringBoot2 全局异常处理
    Intellij IDEA 将工程转换成maven工程 详解
    js性能优化
    JDK故障处理工具箱
    编写高性能的jquery代码
    maven工程解决jar包冲突依赖问题
    spring aop中xml配置文件中标签和属性对应的类
  • 原文地址:https://www.cnblogs.com/mayugang/p/10093646.html
Copyright © 2020-2023  润新知