python笔记-8(logging模块、re模块、栈与队列)
一、Logging模块日志
1、logging导入
Import logging
2、知道5个日志级别的等级关系
Debug->info->warning->error->critical
3、输出5种日志的基本方式
logging.debug ('xxxx') logging.info('xxx') logging.waring('xxx') logging.error('xxx') logging.critical('xxxx')
4、默认情况下5中基本方式的输出情况,只输出了warning/error/critical,即只输出了warining之后的日志
logging.debug('it is debug') logging.info('it is info') logging.warn('it is warm') logging.error('it is error') logging.critical('it is critical') ------------ WARNING:root:it is warm ERROR:root:it is error CRITICAL:root:it is critical
5、修改默认日志级别的方式 basicconfig
logging.basicConfig(level=logging.DEBUG)
6、basicconfig的深入学习
6.1 设置日志输入到文件中,使用filename
filename='mylog.log'
6.2 设置日志的输出格式 如添加日志时间
%(asctime)s 时间
%(filename)s 文件名
%(lineno)d 行数
%(levelname)s 日志等级
%(message)s 日志内容
%(funcname)s 函数名
#format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')
import logging import datetime print('5个级别,默认输出warm及以上的日志') logging.basicConfig( filename='log.log', level=logging.DEBUG, datefmt='%Y/%m/%d %H:%M:%S %b,%a', format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s') #此时屏幕上不输出 还能输出进程号 先知道就行 logging.debug('it is debug') logging.info('it is info') logging.warn('it is warm') logging.error('it is error') logging.critical('it is critical') --------- 2011/01/01 22:19:42 Mar,Sat 20110116_logging_mod_1.py[line:10] DEBUG it is debug 2011/01/01 22:19:42 Mar,Sat 20110116_logging_mod_1.py[line:11] INFO it is info 2011/01/01 22:19:42 Mar,Sat 20110116_logging_mod_1.py[line:12] WARNING it is warm 2011/01/01 22:19:42 Mar,Sat 20110116_logging_mod_1.py[line:13] ERROR it is error 2011/01/01 22:19:42 Mar,Sat 20110116_logging_mod_1.py[line:14] CRITICAL it is critical
7、logging模块的高级应用 4个类的使用
了解logging模块的4个类:
Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
7.1 定义logger,设置level总开关
import logging #step 1 logger1=logging.getLogger('logger1')#实体化一个logger 可以给其他模块是使用的 logger1.setLevel(logging.DEBUG)#定义日志级别 总开关 如果这里做了限定只打印error之后 下面的日志等级也无法打印error之前的 logger2=logging.getLogger('logger2') logger2.setLevel(logging.DEBUG)
7.2 定义handle 指定日志输出的位置,屏幕,文件,还能通过邮件发送,本文不描述邮件发送的方法
#step2 定义handler #7.2.1 #屏幕handler logging.StreamHandler() scream_handler=logging.StreamHandler() scream_handler.setLevel(logging.DEBUG) #7.2.2 #文件handler logging.FileHandler('') file_handler=logging.FileHandler('logxxx.log') file_handler.setLevel(logging.DEBUG)
7.3 定义formatter 定义输出内容的格式
#文件formatter f_formater=logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s','%Y%b%d-%H:%M:%S') #屏幕formater s_formater=logging.Formatter('%(asctime)s-%(levelname)s-%(message)s','%Y-%m-%d/%X')
7.4 formatter与handler关联
#step4 formatter与handler关联 file_handler.setFormatter(f_formater) scream_handler.setFormatter(s_formater)
7.5 #给logger对象添加handler 一个logger可以添加多个handler
logger1.addHandler(file_handler) logger2.addHandler(file_handler) logger2.addHandler(scream_handler) logger1.debug('loger1 ******************debug') logger1.info('loger1 ******************infor') logger1.warning('logger1 ******************warning') logger1.error('logger1 ******************error') logger1.critical('logger1 ******************critical') logger2.debug('loger2 debug') logger2.info('loger2 infor') logger2.warning('logger2 warning') logger2.error('logger2 error') logger2.critical('logger2 critical') ------------------------------------------------ 2018-03-04/01:57:26-DEBUG-loger2 debug 2018-03-04/01:57:26-INFO-loger2 infor 2018-03-04/01:57:26-WARNING-logger2 warning 2018-03-04/01:57:26-ERROR-logger2 error 2018-03-04/01:57:26-CRITICAL-logger2 critical
8、日志切割
from logging import handler
#8.1 按时间切割
TimedRotatingFileHandler(filename='time.log',when='M',interval=1,backupCount=2,encoding='utf-8')
#8.2 按大小切割
.RotatingFileHandler(filename='file.log',maxBytes=16,backupCount=5,encoding='utf-8')
import logging from logging import handlers import time timelog=logging.getLogger('time.log') timelog.setLevel(logging.DEBUG) filelog=logging.getLogger('file.log') filelog.setLevel(logging.DEBUG) time_handler=handlers.TimedRotatingFileHandler(filename='time.log',when='M',interval=1,backupCount=2,encoding='utf-8') time_handler.setLevel(logging.DEBUG)
file_handler=handlers.RotatingFileHandler(filename='file.log',maxBytes=16,backupCount=5,encoding='utf-8') file_handler.setLevel(logging.DEBUG) formatter1=logging.Formatter('%(asctime)s-%(levelname)s-%(message)s','%Y-%m-%d/%X') time_handler.setFormatter(formatter1) file_handler.setFormatter(formatter1) timelog.addHandler(time_handler) filelog.addHandler(file_handler) for i in range(8): print(i) timelog.debug('123') time.sleep(10) ------------------------------------ filelog.debug('这是一个日志测试') filelog.debug('测试日志大小自动切割功能') filelog.debug('测试结束')
二、re模块 正则表达式
Re 模块 只是把匹配的那一段内容截取出来 不会显示前后内容
1、re模块
用于正则表达式对字符串的处理
2、match与group的使用
match函数
规定:从头开始匹配 使用group能查看 只能匹配一个
使用语法:matach (规则 ,字符串)
输出方式:group()输出
>>> a=re.match('ip','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() --------------------- 'ip'
3、Search与findall
规定:search和findall都全文匹配检索,相比于match而言,search与findall更为常用。
使用方法
re.search(‘条件’,’string’)
re.findall(‘条件’,’string’)
输出方式:
Search的匹配结果和match一样,需要使用.group()来输出
Findall的结果赋值给变量后,可以直接输出,变现为一个列表的形式
>>> a=re.findall('.{3,6}','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a -------------------------- ['ipaddr', ' 192.1', '68.1.1', ' mask ', '255.25', '5.255.']
4、’.’ 点的使用 表示匹配除了\n之外的任意一个字符 此处先不考虑flag
>>> a=re.match('.','inet 127.0.0.1 netmask 255.0.0.0') >>> a.group() 'i' >>> a=re.match('...','inet 127.0.0.1 netmask 255.0.0.0') >>> a.group() 'ine' >>> a=re.match('....','inet 127.0.0.1 netmask 255.0.0.0') >>> a.group() 'inet'
5、^与$的使用 此处可以设置flag 暂时不考虑
^表示匹配开头,和match一致
$匹配结尾
a6=re.search('k$','are you ok') print(a6.group())
6、*匹配前一个字符 0次或者多次 优先多次
7、+匹配前一个字符1次或者多次
* 与+号 的对比 * 0次可以匹配到空串 (最长匹配原则,会尽量匹配到最长再结束)
>>> a=re.match('\w+','@ipaddr 192.168.1.1 mask 255.255.255.0') >>> a >>> print(a)#w表示A-Z及数字,特殊字符无法匹配,所以此处返回null None >>> a=re.match('\w*','@ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group()#*匹配0个也属于匹配,所以不会返回null,会返回空字符串 ' ' >>> print(a) <_sre.SRE_Match object; span=(0, 0), match=''> >>> >>> a=re.match('\w*','ipad@dr 192.168.1.1 mask 255.255.255.0') >>> a.group() 'ipad' #最长匹配,一直匹配到无法匹配了
8、?匹配0次或者1次 优先1次
>>> a=re.match('\w?','@ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() ---------------------------- ''#空串
-
9、{x } 匹配前一规则多少次
>>> a=re.match('.{3}','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() 'ipa' >>> a=re.match('.{0}','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() '' >>> a=re.match('.{6}','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() 'ipaddr' >>>
10、{x,y} 能匹配长的尽量匹配长的
>>> a.group() 'ipaddr' >>> >>> a=re.findall('.{3,6}','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a ['ipaddr', ' 192.1', '68.1.1', ' mask ', '255.25', '5.255.']
11、x|y 满足x或y任意一个条件都可以 同时满足 匹配左边
>>> a=re.match('ip|IP','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() 'ip' >>> a=re.match('ip|IP','IPaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() 'IP' >>> a=re.match('.{3}|.{6}','ipaddr 192.168.1.1 mask 255.255.255.0') >>> a.group() 'ipa'
12、分组 group groups groupdict ?P<city>的使用
我们可以使用()对匹配规则进行分组
匹配结果的不同输出方式
group:所有匹配结果组合成一个string输出
Groups:将匹配结果以括号为切割分成不同的段,以元组形式展现
Groupdict()与?P<自定义标题>结合,可以组成key-value形式的字段,便于处理
下面以身份证号码来演示结果:
a34=re.search('(?P<省份>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{6})','550101201811118911') print(a34.groups()) print(a34.group()) print(a34.groupdict()) ------------------------- ('5501', '01', '201811') 550101201811 {'省份': '5501', 'city': '01', 'birthday': '201811'}
13、\A \Z的表示含义 等同于^ $
注意点:\A \Z ^ $时,需要从整个字符串的头尾入手来分析
re.search('\A\d.*\d\Z','333199995555alex') >>> a=re.search('\A\d.*\d\Z','333199995555alex3') >>> print(a) <_sre.SRE_Match object; span=(0, 17), match='333199995555alex3'> >>> a.group() '333199995555alex3' >>>
注意:这个是易错点
14、\d与\D 的表示含义0-9 与非0-9
15、\w与\W 的表示含义A-Z0-9a-z与 非A-Z0-9a-z
16、\s 的表示含义 匹配空白符号 包括\n \t \r
>>> re.findall('\s','\naaa\tbajidfi\radjkfi\n') ['\n', '\t', '\r', '\n'] re.findall('\s','\naaa\tbajidfi\radjkfi\n')
17、[a-x]这种写法与[^a-x]的写法,此处^表示非的意思,需要注意
对于[^]非的理解[^()]指 除了括号以外的任意字符 [^0-9]除了0-9以外的任意字符
18、findall 与split切割字符串的用法对比及split与()括号的结合使用
Split进行切割,会有空串出现 Split进行切换,可以结合括号来对字符串进行分段,且保留被匹配的部分 注意空串的存在
>>> re.findall('\d+','ad23123jkjojo123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n') ['23123', '123', '545', '6', '4', '3', '4', '5', '1', '4', '4', '213', '4'] >>> re.split('\D+','ad23123jkjojo123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n') ['', '23123', '123', '545', '6', '4', '3', '4', '5', '1', '4', '4', '213', '4', ''] >>> >>> re.split('(\D+)','ad23123jkjojo123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n') ['', 'ad', '23123', 'jkjojo', '123', 'jkoj', '545', 'kjo', '6', 'jl', '4', 'jnu', '3', 'n', '4', 'nl', '5', 'n', '1', 'kj', '4', 'hkj', '4', 'n', '213', 'k', '4', 'n', ''] >>>
19、re.sub 替换内容
#与split一样,会有空串出现,被替换为相应的字符,需要注意 #语法sub(‘规则’,’替换成的形势’,’需要被处理的字符串’,‘替换次数’,‘次数不写为全部替换’) >>> re.sub('\D+','|','ad23123jkjojo123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n') '|23123|123|545|6|4|3|4|5|1|4|4|213|4|' >>> re.sub('\D+','|','ad23123jkjojo123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n',count=2) '|23123|123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n' >>> re.sub('\D+','|','ad23123jkjojo123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n',count=4) '|23123|123|545|6jl4jnu3n4nl5n1kj4hkj4n213k4n' >>> re.sub('\D+','|','ad23123jkjojo123jkoj545kjo6jl4jnu3n4nl5n1kj4hkj4n213k4n') '|23123|123|545|6|4|3|4|5|1|4|4|213|4|' >>>
19、反斜杠的困扰
一个\组成\'
两个\\ 组成正则表达式一个\ 也是有歧义
三个\\\ 组织一个正则表达式的\及一个转义\'
四个\\组成两个正则表达式\\ 变成一个真实的字符串\ 此类可以用r来解决
20、三个flag的使用 flag I、M、S
Flags=re.I #含义:re.I 忽略大小写 >>> a=re.match('ip','IPADDR 192.168.1.1',flags=re.I) >>> a.group() 'IP' >>> a=re.match('ip','IPADDR 192.168.1.1') >>> print(a) None >>> Flags=re.M 多行模式 影响^ $ Flags=re.S 点任意匹配模式 >>> a=re.match('^\d.+\d$','3aaaaa4\nddddd5',flags=re.M) >>> a.group() '3aaaaa4' >>> a=re.match('^\d.+\d$','3aaaaa4\nddddd5') >>> a.group() Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'NoneType' object has no attribute 'group' #注意这里为什么报错 >>> a=re.match('^\d.+\d$','3aaaaa4\nddddd5',flags=re.S) >>> a.group() '3aaaaa4\nddddd5' >>>
三、堆栈与队列的操作
1、队列与堆栈的浅认识,队列先进先出、堆栈先进后出。
2、使用列表的insert(0)、append、pop、pop(0) 分别实现队列和堆栈的入队出队,入栈出栈