学习python课程第二十天
Posted lvyipin1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习python课程第二十天相关的知识,希望对你有一定的参考价值。
一. logging模块
1. 日志的级别分别有:
logging.debug (‘‘这是一个调试信息‘‘) #10 级别最低
logging.info (‘一些常规的信息‘) #20
logging.warning (‘警告信息‘) #30
logging.error (‘错误信息‘) #40
logging.critical (‘严重错误‘) #50
# 在logging模块中又对应的常量用来表示级别
默认情况下 默认级别是#30 waming 日志输出位置是控制台
2. 自定义日志的配置
示例:
logging.basicConfig(
filename = ‘a.log‘
filemode = ‘at‘
level = 10,
format = ‘%(asctime)s %(levelname)s %(funcName)s %(lineno)s %(message)s‘,
datefmt = ‘%Y-%m-%d %X %p‘)
logging.debug(‘这是调试信息‘)
可用参数:
filename : 用指定的文件名创建FiledHandler (后边会具体讲解handler的概念) , 这样日志会被存储到
指定的文件中
filemode : 文件打开的方式, 在指定了filename时使用这个参数, 默认值为 ‘a‘ 还可以指定为 ‘w‘ .
format : 指定handler使用的日志显示格式
datefmt : 指定日期的格式
level : 设置root logger (后边会讲解具体的概念) 的日志级别
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:35 , 897‘.逗号后面是毫秒
%(therad)d : 线程ID, 可能没有
%(theradName)s : 线程名 可能没有
%(process)d: 进程ID, 可能没有
%(message)s : 用户输出的消息
3. 如何能够同时输出到多个位置 ?
logging中的四个核心角色 !!
1. logger 生成器
2. handler 处理器
3. filter 过滤器
4. formatter 格式化
一条日志完整的生命周期 :
1. 由logger 产生日志 -> 2. 交给过滤器判断是否被过滤 -> 3. 将日志消息分发给绑定的所有处理器. -> 4.
处理器按照绑定的格式化对象输出日志
其中, 第一步会先检查日志的级别, 如果低于设置的级别, 则不执行 第四步 如果不指定格式则按照默认格式
1. 创建一个日志生成器 :
mylog = logging.getLogger(‘mylog‘)
# 设置生成器级别
mylog.setLevel(logging.DEBUG)
2. 创建一个日志处理器 :
fh = logging.FileHandler(‘b.log‘,encoding=‘utf-8‘)
3. 创建一个格式处理器
fm = logging.Formatter(
‘%(asctime)s %(levelname)s %(funcName)s %(lineno)s %(message)s‘ ,
datefmt = ‘%Y-%m-%d %X %p‘)
4. 将三个对象进行关联
mylog.addHandler(fh)
fh.setFormatter(fm)
# 测试
mylog.debug(‘mylog 的 测试‘)
4. 日志的继承
可以将一个日志指定为另一个日志的子日志, 或子孙日志, 当存在继承关系时, 子孙级日志收到日志时
会将该日志向上传递,
指定继承关系 :
log1 = logging.getLogger(‘father‘)
log2 = logging.getLogger(‘father.son‘)
log3 = logging.getLogger(‘father.son.grandson‘)
# 默认值为True, 表示 有继承关系. 当子的日志产生日志时, 给他父级以及父级以上都发一份.
如果不需要, 就设置为False
log3.propagate = False
fh = logging.FileHandler(‘c.log‘.encoding=‘utf-8‘)
fm = logging.Formatter(
‘%(asctime)s %(levelname)s %(funcName)s %(lineno)s %(message)s‘ ,
datefmt = ‘%Y-%m-%d %X %p‘)
log1.addHandler(fh)
log2.addHandler(fh)
log3.addHandler(fh)
fh.setFormatter(fm)
# 测试
log3.error(‘测试‘)
# 取消传递
log3.propagate = False
log1.warning(‘father log‘)
log2.warning(‘father.son log‘)
log3.warning(‘father.son.grandson log‘)
5. 通过字典配置日志模块
每次都要编写代码来配置,非常麻烦, 我们最好能够写一次到处用.
logging.config.dictConfig()
6. 加载配置 :
import logging.config
logging.config.dictConfig (LOGGING_DIC)
logging.getLogger(‘aa‘).debug(‘测试‘)
# getLogger参数就是对应字典中loggers的key 如果没有匹配到key 什么都不做, 很多情况我们的日志
可能对应不同的业务模块 我们需要在日志中体现业务信息 那问题是, 我的配置中不可能预先知道所有
的业务名称 这时候我们可以将key设置为空, 这样以来, 获取的时候如果找不到对应的就用默认的. 并且
日志对象的名称会变成你传入的key
7. 流 处理器
log1 = logging.getLogger(‘a‘)
#输出文件
fh = logging.FileHandler(‘c.log‘,encoding=‘utf-8‘)
#输出到控制台
sh = logging.StreamHandler()
log1.addHandler(sh)
log1.addHandler(fh)
fm = logging.Formatter(
‘%(asctime)s %(levelname)s %(funcName)s %(lineno)s %(message)s‘,
datefmt = ‘%Y-%m-%d %X %p‘)
sh.setFormatter(fm)
log1.warning(‘测试2!‘)
import lib.common
logger = lib.common.get_logger()
def login():
logger.debug(‘测试 测试!‘)
login()
二. hashlib模块
1. 什么是hash lib
hash是一种算法, 是将一个任意长的数据, 根据计算, 得到一个固定长度特征码
特征: 不同输入, 可能会有相同的结果. 但是几率特别小.
相同的输入 必然得到相同的结果
由于散列(特征)的性质 从原理来看是不可能反解的.
用来验证 两个输入的数据是否一致
使用场景
1. 密码验证
123432 44sdas4kkas4tk
client 加密后的结果. server 拿到加密后.
2. 验证数据是否被篡改过. 比如游戏安装包. 可以对比一下有没有被改过
为了防止别人撞库成功 可以提升密码的复杂度. 其次可以为密码加盐 (加点内容进去)
示例:
import hashlib
m = hashlib.md5(‘aaa.encode(‘utf-8‘)‘)
print (len(m.hexdigest()))
# 撞库破解的原理. 有人事先把常见的明文和密文的对应关系存到了数据库中.
运气好就能查到
# 可以选择密文的长度,
h1 = hashlib.sha512(‘123‘.encode(‘utf-8‘))
print(h1.hexdigest())
加盐:
m = hashlib.md5(‘321‘.encode(‘utf-8‘))
# 加
m.update(‘asfasfafasf‘.encode(‘utf-8‘))
print (m.hexdigest())
在创建的时候必须加盐的类型
import hmac
h = hmac.new(‘asdad‘.encode(‘utf-8‘))
h.update(‘123‘.encode(‘utf-8‘))
print(h.hexdigest())
三. re 模块
re是Regular Expression 的简称, 表示正则表达法
什么是正则表达式 ?
表达式指的是默写带有特殊含义的符号或者符号组成的式子
正则表达式是对字符进行处理的逻辑公式, 使用特殊字符或者一些特殊字符的组合,
组成一个规则字符串, 这个规则字符串用来表达对字符的过滤逻辑
支持的字符及其表达的含义.
re 的使用:
在爬虫里大量的使用 其实有框架帮你封装了这些复杂的正则
在网站和手机app的注册功能中大量使用, 例如判断你的邮箱地址是否正确,
1. 普通匹配.
s w d .
2. 重复匹配.
*: 任意, +:1- 无穷 ?:0 - 1
3. 范围匹配
a|b|c [abc] [0-9] [a-z] [A-Z] [0-9a - zA - Z] 注意: 仅匹配一个字符. 它的范围是根据ascii码表
print(re.findall("w","1aA_*")) # 匹配数字字母下划线
print(re.findall("W","1aA_*,")) # 匹配非数字字母下划线
print(re.findall("s"," f")) # 匹配任意空白字符
print(re.findall("S"," 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码表
4.匹配位置
print(re.findall("Ad","123abc1*")) # 从字符串的开始处匹配
print(re.findall("d","123abc1*9 ")) # 从字符串的结束处匹配 注意把写在表达式的右边
print(re.findall("d$","123abc1*9")) # 从字符串的结束处匹配 如果末尾有换行 换行不会参与匹配
print(re.findall("^d","s1asasas121 ")) # 从字符开始匹配数字
以上是关于学习python课程第二十天的主要内容,如果未能解决你的问题,请参考以下文章