第五章 模块之 logging、copy、re
5.12 logging 日志模块
报警等级
CRITICAL = 50 # 最高
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0 # 最低日志处理本质:Logger/FileHandler/Formatter
应用:统计用;做故障排除debug;记录错误,完成代码优化
# 示例一
import logging
file_handler1 = logging.FileHandler('x2.log', 'a', encoding='utf-8') # 构造参数
fmt1 = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s")
file_handler1.setFormatter(fmt1)
# file_handler2 = logging.FileHandler('x2.log', 'a', encoding='utf-8')
# fmt2 = logging.Formatter(fmt="%(asctime)s: %(message)s")
# file_handler2.setFormatter(fmt2)
logger = logging.Logger('xxxxxx', level=logging.ERROR)
logger.addHandler(file_handler1)
# logger.addHandler(file_handler2)
# 示例二
import logging
logging.basicConfig( # 函数各参数
filename='cmdb1.log', # 日志文件名称
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', # 指定日志输出格式和内容
datefmt='%Y-%m-%d %H:%M:%S %p', # 指定时间格式
level=logging.ERROR # 日志报警等级
)
# 无效 日志只配置一次
logging.basicConfig(
filename='cmdb2.log',
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=logging.ERROR
)
logging.error('alex') # 报警内容
logging.basicConfig函数各参数:
filename: 指定日志文件名
filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
datefmt: 指定时间格式,同time.strftime()
level: 设置日志级别,默认为logging.WARNING
stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略
---------------------logging.basicconfig
使用方便
不能实现编码问题;不能同时向文件和屏幕输出
logging.debug logging.warning
logger对象 复杂的创建流程
创建一个logger对象
创建一个文件操作符
创建一个屏幕操作符
创建一个格式
操作;
给logger对象绑定 文件操作符
给logger对象绑定 屏幕操作符
给文件操作符设定格式
给屏幕操作符设定格式
import logging
logger = logging.getLogger() # 创建一个logger对象
fh = logging.FileHandler('log.log') # 创建一个文件操作符
sh = logging.StreamHandler() # 创建一个屏幕操作符
logger.addHandler(fh) # 给logger对象绑定 文件操作符
logger.addHandler(sh) # 给logger对象绑定 屏幕操作符
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 创建一个格式
fh.setFormatter(formatter) # 给文件操作符设定格式
sh.setFormatter(formatter) # 给屏幕操作符设定格式
logger.warning('message') #
推荐处理日志方式
import logging
file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers=[file_handler,],
level=logging.ERROR
)
logging.error('你好')# 日志切割
import time
import logging
from logging import handlers
# file_handler = logging.FileHandler(filename='x1.log', mode='a', encoding='utf-8',)
file_handler = handlers.TimedRotatingFileHandler(filename='x3.log', when='s', interval=5, encoding='utf-8')
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
handlers=[file_handler,],
level=logging.ERROR
)
for i in range(1,100000):
time.sleep(1)
logging.error(str(i))注意事项
# 在应用日志时,如果想要保留异常的堆栈信息。
import logging
import requests
logging.basicConfig(
filename='wf.log',
format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=logging.ERROR
)
try:
requests.get('http://www.xxx.com')
except Exception as e:
msg = str(e) # 调用e.__str__方法
logging.error(msg,exc_info=True)
5.13 copy
5.14 re模块
转义符
正则表达式中的转义符在python的字符串中也刚好有转移的作用但是正则表达式中的转义符和字符串中的转义符并没关系,且还容易有冲突,为了避免这种冲突,我们所有的正则都以在工具中的测试结果为结果,然后只需要在正则和待匹配的字符串外面都加r即可
print('\\\\n') # //n
print('\\n') # /n
print(r'\\n') # //n
print(r'\n') # /nre.findall 匹配字符串中所有规则的项,返回一个列表;未匹配返回一个空列表
import re
ret = re.findall('\d+','asadf451sdfdfb645d')
print(ret) # ['451', '645']re.search 会从头到尾从带匹配,匹配字符串取出第一个符合条件的项,如果匹配到了,返回一个对象,用group取值;如果没匹配到,返回None,不能用group,会报错
import re
ret = re.search('\d+','asadf451sdfdfb645d')
print(ret) # <_sre.SRE_Match object; span=(5, 8), match='451'> span 是索引 match 是匹配到的项
if ret:
print(ret.group()) # 451
re.match 会从头匹配字符串中取出从第一个字符开始是否符合规则,如果符合,就返回对象,用group取值;如果不符合,就返回None,相当于 match = search + ^正则
import re
ret = re.match('\d+','45adf451sdfdfb645d')
print(ret)
if ret:
print(ret.group())re.finditer 在查询的结果超过1个的情况下,能够有效的节省内存,降低空间复杂度,从而也降低了时间复杂度
import re
ret = re.finditer("\d+",'cdfz56x31d144df'*1000)
print(ret) # <callable_iterator object at 0x000002541A7874A8> 迭代器
for i in ret: # 循环迭代出每个元素
print(i.group()) # 56 31 144 ......compile 在同一个正则表达式重复使用多次的时候使用能够减少时间的开销,属于内置函数
import re
ret = re.compile('\d+')
print(ret) # re.compile('\\d+')
r1 = ret.search('alex83')
print(r1) # <_sre.SRE_Match object; span=(4, 6), match='83'>
r2 = ret.findall('wusir74')
print(r2) # ['74']
r3 = ret.finditer('taibai40')
for i in r3:
print(i.group()) # 40re.split() 分割,根据正则规则切割,返回列表,默认不保留切掉的内容
import re
ret1 = re.split('\d\d','alex83wusir74taibai') # 默认自动保留分组中的内容
print(ret1) # ['alex', 'wusir', 'taibai']
ret2 = re.split('\d(\d)','alex83wusir74taibai')
print(ret2) # ['alex', '3', 'wusir', '4', 'taibai']re.sub() 替换,默认替换所有,可以使用替换深度参数
re.subn() 替换,返回元祖
import re
ret1 = re.sub('\d','D','alex83wusir74taibai')
print(ret1) # alexDDwusirDDtaibai
ret2 = re.sub('\d','D','alex83wusir74taibai',1)
print(ret2) # alexD3wusir74taibai
ret3 = re.subn('\d','D','alex83wusir74taibai')
print(ret3) # ('alexDDwusirDDtaibai', 4)分组
findall遇到正则表达式中的分组,会优先显示分组中的内容
import re
ret = re.findall('\d(\d)','sdfgfgvbnk83')
print(ret) # ['3']split遇到正则表达式中的分组,会保留分组中本来应该被切割掉的内容
import re
ret1 = re.split('(\d\d)','alex83wusir74taibai') # 默认自动保留分组中的内容
print(ret1) # ['alex', '83', 'wusir', '74', 'taibai']group(加参数)
s1 = '<h1>wahaha</h1>'
ret = re.search('<(\w+)>(.*?)</\w+>',s1)
print(ret) # <_sre.SRE_Match object; span=(0, 15), match='<h1>wahaha</h1>'>
print(ret.group(0)) # group参数默认为0 表示取整个正则匹配的结果 <h1>wahaha</h1>
print(ret.group(1)) # 取第一个分组中的内容 h1
print(ret.group(2)) # 取第二个分组中的内容 wahaha分组命名 (?P<名字>正则表达式)
search 取分组中的内容 通过索引;通过组名取
s1 = '<h1>wahaha</h1>'
ret = re.search('<(?P<tag>\w+)>(?P<cont>.*?)</\w+>',s1)
print(ret) # <_sre.SRE_Match object; span=(0, 15), match='<h1>wahaha</h1>'>
print(ret.group(0)) # group参数默认为0 表示取整个正则匹配的结果 <h1>wahaha</h1>
pprint(ret.group('tag')) # 取tag分组中的内容
print(ret.group('cont')) # 取cont分组中的内容分组引用 (?P=组名) 这个组中的内容必须完全和之前已经存在的组匹配到的内容一模一样
import re
s1 = '<h1>wahaha</h1>'
ret = re.search('<(?P<tag>\w+)>.*?</(?P=tag)>',s1)
print(ret.group('tag')) # h1取消分组优先 (?:)
# 有的时候我们想匹配的内容包含在不相匹配的内容当中,这个时候只需要把不想匹配的先匹配出来,再通过手段去掉
import re
ret=re.findall(r"\d+\.\d+|(\d+)","1-2*(60+(-40.35/5)-(-4*3))")
print(ret) # ['1', '2', '60', '', '5', '4', '3']
ret.remove('')
print(ret) # ['1', '2', '60', '5', '4', '3']
[] 和 [^] 带有特殊意义的元字符到字符组内大部分都会取消它的特殊含义
[()+*.]
[(
\-)] -的位置决定了它的意义,写在字符组的第一位位置或者最后一个位置就表示一个普通的横杠写在字符组的其他任何位置都会表示一个范围
练习
# 检测用户输入的内容是否是一个合法的身份证号 网页的合法输入(手机号码 qq号码 银行卡号 邮箱地址)
'^[1-9]\d{14}(\d{2}[\dx])?$'
import re
inp = input('>>>').strip()
re.match('[1-9]\d{14}(\d{2}[\dx])?$',inp) # 首选
re.search('^[1-9]\d{14}(\d{2}[\dx])?$',inp)
re.findall('^[1-9]\d{14}(\d{2}[\dx])?$',inp)
第五章 模块之 logging、copy、re的更多相关文章
- Python学习系列----第五章 模块
5.1 如何引入模块 在Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入.在调用math模块中的函数时,必须这样引用: ...
- 第五章 模块之random 、hashlib、time /datetime
5.2 random 返回随机生成的一个实数 random.randint() 返回随机生成的一个实数 import random #调用模块def get_random_code(length=6 ...
- 第五章 模块之 shtil 、 json / pickle、importlib、collections
5.8 shtil 高级的 文件.文件夹.压缩包 处理模块 shutil.rmtree 删除目录 import shutilshutil.rmtree(path) shutil.move 重命名:移动 ...
- 第五章 模块之 getpass、sys、os
5.5 getpass 密码不显示(只能在终端运行) 密码不显示(只能在终端运行) import getpasspwd = getpass.getpass('请输入密码:')if pwd == '1 ...
- 第五章 模块之 struct、dis、正则表达式、异常处理
5.15 struct模块 pack 能够把所有的数字都固定的转换成4字节 5.16 dis dis.dis 查看计算机指令 5.16 正则表达式 基础 正则表达式概念: 是一种规则(元字符,量词) ...
- Python第五章__模块介绍,常用内置模块
Python第五章__模块介绍,常用内置模块 欢迎加入Linux_Python学习群 群号:478616847 目录: 模块与导入介绍 包的介绍 time &datetime模块 rando ...
- 简学Python第五章__模块介绍,常用内置模块
Python第五章__模块介绍,常用内置模块 欢迎加入Linux_Python学习群 群号:478616847 目录: 模块与导入介绍 包的介绍 time &datetime模块 rando ...
- 第十五章、线程之queue模块的各种队列
目录 第十五章.线程之queue模块的各种队列 一.Queue 二.LifoQueue堆栈 三.PriorityQueue优先级队列 第十五章.线程之queue模块的各种队列 一.Queue impo ...
- 《Linux内核设计与实现》课本第五章学习笔记——20135203齐岳
<Linux内核设计与实现>课本第五章学习笔记 By20135203齐岳 与内核通信 用户空间进程和硬件设备之间通过系统调用来交互,其主要作用有三个. 为用户空间提供了硬件的抽象接口. 保 ...
随机推荐
- Liskov替换原则(LSP)
OCP背后的主要机制是抽象和多态.在静态类型语言中,比如C++和Java,支持抽象和多态的关键机制之一是继承.正是使用了继承,才可以创建实现其基类中抽象方法的派生类.是什么设计规则在支配着这种特殊的继 ...
- 实验五 遇到的问题:openssl: error while loading shared libraries: libssl.so.1.1
遇到的问题 命令行:linux@ubuntu64-vm:~/exp/exp5$ openssl enc -aes-128-cbc -in test_aes.txt -out out.txt -pass ...
- [Web前端] WEEX、React-Native开发App心得 (转载)
转自: https://www.jianshu.com/p/139c5074ae5d 2018 JS状态报告: https://2018.stateofjs.com/mobile-and-deskto ...
- ASP.NET_微信JS_SDK调用
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;usi ...
- 讲座 - Transposable elements, non-coding RNAs and epigenetic control in embryonic stem cells
Dr. Andrew Paul HutchinsDepartment of BiologySouthern University of Science and Technology, Shenzhen ...
- https://pingcap.com/blog-cn/flame-graph/
https://pingcap.com/blog-cn/flame-graph/ 因为 TiKV 是自己内部使用了 jemalloc,并没有用系统的 malloc,所以我们不能直接用 perf 来探查 ...
- SVN创建分支/合并/切换使用
原文地址:https://blog.csdn.net/lisq037/article/details/17501327 最近接项目要求,要在svn主干上创建分支,用分支来进行程序的bug修改,而主干上 ...
- SQL Server 将查询结果集以XML形式展现 for xml path
for xml path,其实它就是将查询结果集以XML形式展现 双击打开
- NET 4.5 中新增的特性调用者信息特性CallerMemberNameAttribute/CallerFilePathAttribute/CallerLineNumberAttribute
标题中所说的三个特性 CallerMemberNameAttribute / CallerFilePathAttribute / CallerLineNumberAttribute 我们统称为调用者信 ...
- Python3入门(十三)——常用内置模块之URL模块urlib
见名知意,一系列用于URL的操作 当然了,主要是用于web爬虫等处理(发送Get/Post请求,处理响应等),暂不展开, 参考:https://www.liaoxuefeng.com/wiki/101 ...