• Python课程回顾(day20)


    常用模块3

    一、logging模块

    日志模块
    import logging
    
    logging.basicConfig(
        filename='a.log',   # 指定文件打印路径,不指定文件名会默认打印到控制台
        filemode='a',       # 默认是a模式,可以不写
        format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
        datefmt='%Y-%m-%d %X %p',  # 定制(asctime)的时间格式
        level=10            # 设置日志的级别,代表当前级别及以上级别都可以打印
    
    )
    #  打印格式
    # %(asctime)s   %(name)s   %(levelname)s       %(module)s:       %(message)s
    #  格式化时间   日志名称     日志的级别     当前使用日志的模块名  日志具体的信息
    logging.debug('调试信息')      # 10
    logging.info('运行结果')       # 20
    logging.warning('一级警告')    # 30       { 不同数字代表不同的级别
    logging.error('二级警告')      # 40
    logging.critical('三级警告')   # 50
    
    # logging模块的四类对象
    # logger  负责产生日志
    logger1 = logging.getLogger('')      # 使用getLogger产生一个产生日志的对象
    
    
    # filter  过滤日志(不常用)
    
    
    # handler 控制日志打印到文件或是终端
    # 可能很多文件都需要用到日志,所以可以在多个文件内打印
    fh1 = logging.FileHandler(filename='a1.log', encoding='utf-8')  # 控制文件打印路径
    fh2 = logging.FileHandler(filename='a2.log', encoding='utf-8')  # 控制文件打印路径
    sh = logging.StreamHandler()  # 控制日志打印到终端
    
    
    # formatter 控制日志的格式
    fmt1 = logging.Formatter(
        fmt='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
        datefmt='%Y-%m-%d %X %p'
    )
    
    fmt2 = logging.Formatter(
        fmt='%(asctime)s - %(message)s',
        datefmt='%Y-%m-%d %X %p'
    )
    
    
    # 让logger1对象产生的日志可以分别打印到不同的地方,要让他们绑定关系
    logger1.addHandler(fh1)
    logger1.addHandler(fh2)     # handler对象
    logger1.addHandler(sh)
    
    
    # 让logger1对象所绑定的handler对象再次绑定打印格式
    fh1.setFormatter(fmt1)
    fh2.setFormatter(fmt1)
    sh.setFormatter(fmt2)
    
    
    # 日志级别
    # 日志级别要必须通过两层关卡(logger1级别,文件级别)才可以正常记录
    logger1.setLevel(10)  # 基础级别,可以打印所有级别的信息
    fh1.setLevel(20)      # 只处理打印大于等于20级别的信息
    fh2.setLevel(30)      # 只处理打印大于等于30级别的信息
    sh.setLevel(40)       # 只处理打印大于等于40级别的信息
    
    logger1.warning('调试信息')    # 注意本层级别要 >= logger1的级别
    
    
    了解:日志继承
    import logging
    
    logger1 = logging.getLogger('grandfather')
    logger2 = logging.getLogger('grandfather.father')    # 继承关系要在设置文件名时将子集放置父集后
    logger3 = logging.getLogger('grandfather.father.son')
    
    sh = logging.StreamHandler()
    fmt3 = logging.Formatter(
        fmt='%(asctime)s - %(message)s',
        datefmt='%Y-%m-%d %X %p'
    )
    sh.setFormatter(fmt3)
    
    logger1.addHandler(sh)
    logger2.addHandler(sh)
    logger3.addHandler(sh)
    
    logger1.setLevel(10)
    logger2.setLevel(10)
    logger3.setLevel(10)
    sh.setLevel(10)
    
    logger3.debug('----------')   # logger3会将得到的所有信息反继承给logger3的所有父集

    二、hashlib模块

    import hashlib    # hash是一种算法,该算法接收传入的内容经过运算后会得到一个hash值

    # 特点1:只要传入的值一样,得到的hash值必然一样
    m = hashlib.md5() # 使用.md5拿到一个hash工厂
    m.update('hello'.encode('utf-8')) # 使用update进行加工
    m.update('world'.encode('utf-8'))
    m.update('klf'.encode('utf-8'))
    print(m.hexdigest()) # hexdigest拿到hash值1079e6f8e24cecd0c41c8841f727b31e


    m.update('helloworldklf'.encode('utf-8'))
    print(m.hexdigest()) # 拿到hash值1079e6f8e24cecd0c41c8841f727b31e


    # 特点2:不能由hash值反解成原本内容
    # 基于hash值的这种特性,我们可以在接收用户输入的时候将用户输入的密码加工成hash值,
    # 再由网络通讯发到我们的服务端进行数据保存,以达到用户密码的安全性。
    # 用户再次校验时只需要跟原本的hash值做对比即可

    # 但考虑到用户的个人习惯与撞库(一些常用密码格式的hash值),用户的密码还是不够安全
    # 这时候我们就需要帮助用户来提高密码安全性:即密码加盐
    user_pwd = 'klf123'

    m = hashlib.md5()
    m.update('abcdefg'.encode('utf-8')) # 在用户密码之前加入其他字符的hash值
    m.update(user_pwd.encode('utf-8')) # 中间是用户密码
    m.update('hijklmn'.encode('utf-8')) # 在用户密码之后加入其他字符的hash值

    print(m.hexdigest()) # 生成新的hash值

    # 注意:加盐的方式是随机的,想要破解就必须知道使用的hash工厂,加盐方式以及加盐位置
    # 服务端反解的时候按照当初加盐的规则来反解即可


    # 特点3:只要使用同一种hash算法,得到的hash值的长度的固定的
    # 这种特点大大降低了用户所传入数据的大小所带来的空间不足
    # 无论用户传入的数据有多大,得到的hash值的长度是固定的

    三、re模块(重点******)

    import re
    # re模块之正则表达式re.findall的应用1:单次匹配
    
    # print(re.findall('w', 'abc 123 
    !@#$%
    	f'))  # 'w'匹配字符串内所有的数字、字母、下划线
    # print(re.findall('W', 'abc 123 
    !@#$%
    	f'))  # 'W'匹配的是字符串所有的非数字字母下划线,若字符串内有则会使用一个斜杠转译后面的斜杠
    
    # print(re.findall('s', 'abc 123 
    !@#$%
    	f'))  # 's'匹配的是字符串内所有的空白字符,('空字符'
    
    	f)
    # print(re.findall('S', 'abc 123 
    !@#$%
    	f'))  # 'S'匹配的是字符串内所有的非空白字符
    
    # print(re.findall('d', 'abc 123 
    !@#$%
    	f'))  # 'd'匹配任意数字(0~9)
    # print(re.findall('D', 'abc 123 
    !@#$%
    	f'))  # 'D'匹配任意非数字
    
    # print(re.findall('alex', 'egon,alex_sb123yxx_sb,lxx_sb'))  # 单纯输入的字符串则会将字符串作为整体全部匹配,若匹配不成功则返回空,有多少个匹配多少个
    
    # print(re.findall('Aalex', 'egon,alex_sb123yxx_sb,lxx_sb'))  # 'A'表示只从头开始找,若匹配不成功则返回空,若匹配成功只匹配一次,不会继续向后匹配
    # print(re.findall('^alex', 'egon,alex_sb123yxx_sb,lxx_sb'))  # 作用等同于大A
    # print(re.findall('alex', 'egon,alex_sb123yxx_sb,lxx_sb'))  # ''表示只从末尾开始找,若匹配不成功则返回空,若匹配成功只匹配一次,不会继续向后匹配
    # print(re.findall('alex$', 'egon,alex_sb123yxx_sb,lxx_sb'))  # '$'作用等同于大Z
    
    # 组合应用之*,$
    # print(re.findall('^abc$', 'abc1'))  # 表示字符串必须为^与$之间的字符串,否则匹配不成功
    
    # ==============================================================================
    
    # re模块之正则表达式的应用2:重复匹配
    
    # print(re.findall('a.c', 'a123c a2c anc aaaaaaac'))
    # .表示匹配除换行符之外的任意'一个'字符,可加多个.,每个点都代表一个字符
    # 结果:在a与c中间只有一个字符的情况下,才会匹配成功
    # print(re.findall('a.c', 'a123c a2c anc aaaaaaac a
    c', re.DOTALL))
    # re.DOTALL表示可以打破'.'不能匹配换行符的定义,当前是可以匹配任意字符的
    
    # print(re.findall('ab?', 'a ab abb abbb abbbb abbbbb'))
    # ?表示?左边的1个字符重复0次或1次(可以是0次,最多是1次)
    # 结果:只要a匹配成功,b可以匹配0次(若为0次则只打印a),最多只匹配1次
    
    # print(re.findall('ab*', 'a ab abb abbb abbbb abbbbb'))
    # *表示*左边的1个字符重复0次或N次(可以是0次,没有最大匹配次数,有多少要多少)
    # 结果:只要a匹配成功,b可以匹配0次(若为0次则只打印a),也可以匹配无限次
    
    # print(re.findall('ab+', 'a ab abb abbb abbbb abbbbb'))
    # *表示*左边的1个字符重复1次或N次(至少是1次,没有最大匹配次数,有多少要多少)
    # 结果:只要a匹配成功,b可以匹配1次(若为0次则不打印),也可以匹配无限次
    
    # print(re.findall('ab{0,1}', 'a ab abb abbb abbbb abbbbb'))
    # {}内可以传入范围,指定匹配的次数,若后面的参数不写则代表N次(等同于*号的作用)
    # 结果:等同于?号的作用
    
    # 组合应用之.*(贪婪匹配)
    # print(re.findall('a.*c', 'ac a123c a%$^$c aasdsdasdad'))
    # .*表示可以匹配任意长度任意字符(除
    ),但*会尽可能的去匹配多个字符
    # 结果:.*的组合会将距离开头最近的a当做起始,将距离末尾最近的c当做结束,形成1个匹配然后结束,不建议使用
    
    # 组合应用之.*?(非贪婪匹配)
    # print(re.findall('a.*?c', 'ac a123c a%$^$c aasdsdasdad'))
    # .*?中的问号的作用就是将贪婪匹配转换成非贪婪匹配
    # 结果:会将距离开头最近的a当做起始,将距离a后面最近的c当做结束,形成一个匹配然后结束
    
    # ==============================================================================
    
    # re模块之正则表达式的应用3:分组()
    
    # print(re.findall('(alex)_sb', 'alex_sb sdasfadsgasgalex_sb'))
    # ()的作用是不影响正则表达式基本的匹配方法的前提下,只打印括号内的内容
    # 结果:若匹配成功后只打印alex
    
    # 组合应用之.*?()(爬取网址)
    # print(re.findall('href="(.*?)"', '<link href="/bundles/admin-new.css?v=Ye9IYl3rG1TPa1mMw-tr9jlbN_BMEt9-1G3QChTzFC01" rel="stylesheet"/>'))
    # 结果:                                      ['/bundles/admin-new.css?v=Ye9IYl3rG1TPa1mMw-tr9jlbN_BMEt9-1G3QChTzFC01']
    
    # ==============================================================================
    
    # re模块之正则表达式的应用4:[]指定范围
    # print(re.findall('a[0-9][0-9]c', 'a1c adc a4c aAc a11c aac'))
    # []内可以使用-号来定义一个范围,英文是a-zA-Z,数字是0-9,在这个自定义范围内的才算匹配成功
    # 结果:会将a与c之间是0-9的字符串匹配出来,若想匹配两位数则需要再加中括号进行再次匹配(会以两个字符去匹配),a1c a4c便不再成立
    # 注意:若中括号内要匹配特殊符号例如+-*^之类的,'-'不可以放在两个符号之间,要放左右两边。
    
    # print(re.findall('^a[0-9]c', 'a1c adc a4c aAc a11c aac'))
    # []内前面加^号就代表取反的意思(原始默认为开头)即不再这个范围内的就匹配成功
    # 结果:a与c之间不是0-9之间的就可以匹配
    
    # 组合应用:
    # print(re.findall('[a-z]+_sb', 'alex_sb egon_sb 123wxxxxxxxxx_sb ryc_sb'))
    # [匹配条件]'+'匹配条件 '+'代表中括号内的条件可以匹配1次或N次,直到遇见不是括号范围内的字符然后与'+'后面的字符做匹配
    # 结果:会优先匹配中括号内的(一直匹配),直到字符不属于中括号范围内的,开始匹配_sb
    # print(re.findall('([a-z]+)_sb', 'alex_sb egon_sb 123wxxxxxxxxx_sb ryc_sb'))
    # 加入小括号来只取名称
    
    # ==============================================================================
    
    # re模块之正则表达式的应用5:| 或者
    # print(re.findall('compan(ies|y)', 'too many companies have bank rupt , and the next one company'))
    # 在|左右两边的内容只要成立一个即匹配成功
    # 结果:在compan后若为ies或为y的情况下,则匹配成功,因为有分组,所以只打印括号内的内容,(ies,y)
    
    # print(re.findall('compan(?:ies|y)', 'too many companies have bank rupt , and the next one company'))
    # 在分组内加入?:则代表打印分组外与分组内的所有内容,不单单只要括号内的内容(companies,company)
    
    # ==============================================================================
    
    # re模块之正则表达式search与match的应用:
    # print(re.search('alex', '123 alex sb egon nb alex sb'))
    # print(re.search('^alex', '123 alex sb egon nb alex sb'))
    # search代表从起始到结束依次匹配,若匹配成功返回第一个匹配成功的对象,可以使用group打印结果
    # 若匹配不成功则返回None,再使用group打印结果则会报错
    # 表达式之前加^代表只匹配起始位置,若不成功则返回None,再使用group打印结果则会报错
    # 一般使用search返回的对象(不加group)判断是否存在你需要找的字符
    
    # print(re.match('alex', '123 alex sb egon nb alex sb'))
    # match代表默认只从起始位置匹配,若匹配成功返回一个对象,使用group打印结果
    # 若匹配不成功则返回None,再使用group打印结果则会报错
    
    # ==============================================================================
    
    # re模块之正则表达式split的应用
    # info = 'a,b c:*d/p'
    # print(re.split('[ ,:\/*]', info))
    # split的原理基本等同于字符串的split,不过re中的split可以使用多个符号来切分
    # 将表达式内的各种符号对字符依次切分,只要字符内包含其中的某个切分符就进行切分
    # 若两个字符之间存在两个或多个切分符则会切出相应的空字符
    
    # ==============================================================================
    
    # re模块之正则表达式sup的应用
    # 要求:将第二个egon替换成大写
    # print(re.sub('(.*?)(egon)(.*?)(egon)(.*?)', r'123EGON5', '123 egon is sb egon 123'))
    # sub的作用基本相同于replace,但sub功能可以在指定位置替换指定的字符
    # 结果:事先将字符分组,然后使用12345可以将分组替换位置,也可以在分组内直接替换字符
    
    # 要求:将is左右两边的单词调换位置lqz123+ is sb09
    # print(re.sub('([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)', r'523416', r'lqz123+ is sb09'))
    # 首先明白单词的定义:由连续的字母组成。
    # 基于这个理念来将字符进行分组,然后将分组调换位置即可
    
    # ==============================================================================
    
    # re模块之正则表达式compile的应用
    # res = re.compile('alex')                   # 使用compile将经常用到的表达式定义成一个变量
    # print(res.findall('alex_sb alex123 ale'))  # 通过变量就可以直接去匹配相应的字符
    

      

  • 相关阅读:
    [转] JS报 “尚未实现” 错误
    分享到国内各SNS网站的代码
    IE8以下版本不支持动态创建的HTML5元素?
    一个较为个性化的出生日期选择
    关于拖拽上传 [一个拖拽上传修改头像的流程]
    用CSS写出漂亮的小三角
    用户自定义模块的实现方案
    纪录一则IE的bug
    onpropertychange 和 oninput
    判断脚本加载完毕
  • 原文地址:https://www.cnblogs.com/lefy11-/p/9813321.html
Copyright © 2020-2023  润新知