在工作中经常要打印一些日志,下面介绍一下python中的logging模块
首先,先了解一下日志的级别,主要分为以下5种:
debug 最低级别,一般开发用来打印一些调试信息
info 正常输出信息,一般用来打印一下正常的操作
warning 一般用来打印报警信息
error 一般打印一些错误信息
critical 一般打印一些致命的错误信息
logging模块中主要有四个类
logger 记录器,应用程序可以通过logger提供的api记录日志,相当于创建一个办公室,让员工在里面工作
handler 处理器 ,处理日志信息,可以将日志保存或者显示在不同的目标区域
filter 过滤器
formatter 日志格式化
日志的输出格式
%(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: 打印日志信息 工作中给的常用格式: format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s' 这个格式可以输出日志的打印时间,是哪个文件第几行输出的,输出的日志级别是什么,以及输入的日志内容。
写日志功能的简单实现
import logging logging.basicConfig(level=logging.ERROR,#大写表示常量 format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',#日志输出格式 filename='a.log',#日志输出到哪个文件 filemode='a'#以追加的形式写入文件 ) logging.debug('我是debug') logging.info('我是info') logging.warning('我是warning') logging.error('我是error') logging.critical('我是critical')
注意了:日志级别排列:debug<info<warning<error<critical,选择了日志级别后,打印该级别以及比这个级别高的日志的内容
上述基本实现了log的写入功能,但是用个问题:日志只是写入了文件,但是在终端中显示不出来,怎样可以两者兼顾呢?
使用logging模块下的handlers
1.创建一个logger对象,相当于创建一个办公室
Logger = logging.getLogger()
2.设置日志的级别
Logger.setLevel(logging.DEBUG)
3.定义日志输出格式
fmt = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')
4.实例化两个对象,StreamHandler 负责在屏幕上显示日志 / TimedRotatingFileHandler 负责向文件中写日志
t = logging.StreamHandler() #实例化StreamHandler,相当于找一个人给你干活 往屏幕上输出 st.setFormatter(fmt) #设置屏幕上显示的格式 th = handlers.TimedRotatingFileHandler( 'my.log',when='d',encoding='utf-8',backupCount=5 #第一个参数是文件名,第二个 when是隔多久生成一个日志,backupCount就是保存几个日志文件 ) #实例化TimedRotatingFileHandler 相当于找一个人给你干活 往文件里面写东西 th.setFormatter(fmt)#设置文件里面写入的格式
5.将两个对象加入logger中
Logger.addHandler(st) #把这两个对象加入到logger里面,也就是把干活的人塞到办公室里面 Logger.addHandler(th)
6.打印log
Logger.debug('my_log debug 信息') Logger.info('my_log info 信息') Logger.warning('my_log warning 信息') Logger.error('my_log error 信息')
完整代码如下:
import logging from logging import handlers Logger = logging.getLogger() #创建一个办公室 Logger.setLevel(logging.DEBUG) #设置日志级别 fmt = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')#定义格式 st = logging.StreamHandler() #实例化StreamHandler,相当于找一个人给你干活 往屏幕上输出 st.setFormatter(fmt) #设置屏幕上显示的格式 th = handlers.TimedRotatingFileHandler( 'my.log',when='d',encoding='utf-8',backupCount=5 #第一个参数是文件名,第二个 when是隔多久生成一个日志,backupCount就是保存几个日志文件 ) #实例化TimedRotatingFileHandler 相当于找一个人给你干活 往文件里面写东西 th.setFormatter(fmt)#设置文件里面写入的格式 Logger.addHandler(st) #把这两个对象加入到logger里面,也就是把干活的人塞到办公室里面 Logger.addHandler(th) Logger.debug('my_log debug 信息') Logger.info('my_log info 信息') Logger.warning('my_log warning 信息') Logger.error('my_log error 信息')
最后封装成一个类,可以以后可以直接使用
import logging from logging import handlers class Logger(object): level_relations = { 'debug': logging.DEBUG, 'info': logging.INFO, 'warning': logging.WARNING, 'error': logging.ERROR, 'crit': logging.CRITICAL } # 日志级别关系映射 def __init__(self,filename,level='info', when='D', back_count=3, fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'): self.logger = logging.getLogger(filename) # 分割日志的单位 S 秒、M 分、 H 小时、 D 天、 W 每星期(interval==0时代表星期一)、midnight 每天凌晨 format_str = logging.Formatter(fmt) #设置日志格式 self.logger.setLevel(self.level_relations.get(level)) #设置日志级别 sh = logging.StreamHandler() sh.setFormatter(format_str) th = handlers.TimedRotatingFileHandler(filename=filename,when=when, backupCount=back_count,encoding='utf-8') th.setFormatter(format_str) self.logger.addHandler(sh) self.logger.addHandler(th) if __name__ == '__main__': log = Logger('haha.log') log.logger.debug('i的是100') log.logger.info('hello wold') log.logger.warning('waring message') log.logger.error('error le ')