logging模块、hashlib模块和re模块
今天学习了logging模块、hashlib模块和re模块
一、logging模块
日志的级别:
logging.debug() #10
logging.info() #20
logging.waring() #30
logging.error() #40
logging.critical() #50
默认级别为waring
默认输出位置为控制台
自定义配置:
import logging
logging.basicConfig()
可用参数:
filename:用制定的文件名创建FileHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为'a'还可指定为'w'。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
可用格式:
%(name)s:Logger的名字,并非用户名,详细查看
%(levelno)s:数字形式的日志级别
%(levelname)s:文本形式的日志级别
%(pathname)s:调用日志输出函数的模块的完整路径名,可能没有
%(filename)s:调用日志输出函数的模块的文件名
%(module)s:调用日志输出函数的模块名
%(funcName)s:调用日志输出函数的函数名
%(lineno)d:调用日志输出函数的语句所在的代码行
%(created)f:当前时间,用UNIX标准的表示时间的浮点表示
%(relativeCreated)d:输出日志信息时的,自Logger创建以来的毫秒数
%(asctime)s:字符串形式的当前时间。默认格式是"2003-07-08 16:49:45,896"。逗号后面的是毫秒。
%(thread)d:线程ID。可能没有
%(threadName)s:线程名。可能没有
%(process)d:进程ID。可能没有
%(message)s:用户输出的信息
案例:
logging.basicConfig(
# filename = 'aaa.log'
filemode = 'at',
datefmt = '%Y-%m-%d %H:%M:%S %P',
format = '%(astime)s %(name)s %(levelname)s %(module) %(message)s',
level = 10
)
logging中的四个核心角色
1.logger生成日志
2.handler 处理日志
3.filter 过滤日志
4.formatter 格式化
一条日志完整的生命周期
1.创建一个日志生成器
mylog = logging.getLogger('mylog')
设置生成器级别
mylog.setLevel(logging.DEBUG)
2.搞一个日志处理器
fh = logging.FileHandler('b.log',encoding = 'utf-8')
3.搞一个格式处理器
fm = logging.Formatter('%(astime)s %(name)s %(levelname)s %(module) %(message)s',datefmt = '%Y-%m-%d %X %p')
4.将三个对象进行关联
mylog.addHandler(fh)
fh.setFormatter(fm)
测试
mylog.debug('mylog 的 测试!')
日志对象的继承关系
可以将一个日志指定为另一个日志的自日志 或子孙日志
当存在继承关系时 子孙级日志收到日志时会将该日志向上传递
制定继承关系:
import logging
log1 = logging.getLogger('mother')
log2 =logging.getLogger('mother.son')
log3 = logging.getLogger('mother.son.grandson')
#handler
fh = logging.FileHandler(filename = 'cc.log',encoding = 'utf-8')
#formatter
fm = logging.Formatter('%(asctime)s %(name)s %(filename)s %(message)s')
#绑定
log1.addHandler(fh)
log2.addHandler(fh)
log3.addHandler(fh)
#绑定格式
fh.setFormatter(fm)
#测试
#log1.error('测试')
log3.error('测试')
#取消传递
log3.propagate = False
#再次测试
log3.errot('测试')
二、 hash lib
hash是一种算法 是将一个任意长的数据 根据计算 得到一个固定长度特征码
特征:不同输入 可能会有相同的结果 几率特别小
相同的输入 必然得到相同结果
由于散列的性质 从原理来看是不可能 反解
用来 验证 两个输入的数据是否一致
使用场景
1.密码验证
2.验证数据是否被篡改 比如游戏安装包 有没有被改过
为了防止别人撞库成功 可用提升密码的复杂度 其次可以为密码加盐(加点内容进去)
例子:
import hashlib
m = hashlib.md5('aaa'.encode('utf-8'))
print(len(m.hexdigest()))
#撞库破解的原理 有人事先把常见的明文和密文的对应关系 存到了数据库中
#运气好就能查询到
pwds = {'aaa':'47adfasgasdgasdgawgag'}
#不同的算法可以解析出不同的密文
h1 = hashlib.sha512('123'.encode('utf-8'))
h2 = hashlib.sha3_512('123'.encode('utf-8'))
h1.hexdigest()
h2.hexdigest()
#加盐
m = hashlib.m5('321'.encode('utf-8'))
m.update('dsfasdfasdfasdfad'.encode('utf-8')
print(m.hexdigest())
三、re模块
主要与正则表达式相关
什么是正则表达式 一堆带特殊意义的符号组成式子
它的作用 处理(匹配 查找 替换)字符串
1.在爬虫中大量使用 其实有框架帮你封装了这些复杂的正则
2.在网站和手机app的主责功能中大量使用 例如判断你的邮箱地址是否正确
import re
print(re.findall("\n","1\n")) # 匹配换行符
print(re.findall("\t","1asasas121 \t")) # 匹配制表符
# ========================范围匹配===========
print(re.findall("\w","1aA_*")) # 匹配数字字母下划线
print(re.findall("\W","1aA_*,")) # 匹配非数字字母下划线
print(re.findall("\s"," \n\r\t\f")) # 匹配任意空白字符
print(re.findall("\S"," \n\r\t\f")) # 匹配任意非空白字符
print(re.findall("\d","123abc1*")) # 匹配任意非空白字符
print(re.findall("\D","123abc1*")) # 匹配任意非空白字符
# print(re.findall("[abc]","AaBbCc")) # 匹配 a b c都行
# print(re.findall("[^abc]","AaBbCc")) # 除了 a b c都行
# print(re.findall("[0-9]","AaBbCc12349")) # 除了 a b c都行
print(re.findall("[a-z]","AaBbCc12349")) # a-z 英文字母
print(re.findall("[A-z]","AaBbC:c😀2349[]")) # A-z 匹配原理 是按照ascII码表
# =========================匹配位置======
print(re.findall("\A\d","123abc1*")) # 从字符串的开始处匹配
print(re.findall("\d\Z","123abc1*9\n")) # 从字符串的结束处匹配 注意把\Z写在表达式的右边
print(re.findall("\d$","123abc1*9")) # 从字符串的结束处匹配 如果末尾有换行 换行不会参与匹配
print(re.findall("^\d","s1asasas121 \t")) # 从字符开始匹配数字