Python的logging模块提供了通用的日志系统,支持debug、info、warn、error、critical多种级别日志,可以方便第三方模块或者应用使用。
1. 日志模块loging的简单案例
#! /usr/bin/env python
# -*- coding:utf-8 -*-
import logging
logging.basicConfig(filename= 'logger.log', level=logging.ERROR)
logging.debug('debug message')
logging.info('info message')
logging.warn('warn message')
logging.error('error message')
logging.critical('critical message')
logging.info等可以在程序的合适地方打印,在logger.log文件中打印如下:
ERROR:root:error message
CRITICAL:root:critical message
因为通过level=logging.ERROR设置日志级别为ERROR,所以输出日志级别大于ERROR的日志信息。
2. logging的重要概念
1. Logger
Logger是一个树形层级结构,在使用debug、info、warn、error、critical之前必须创建Logger实例,即创建一个记录器,如果没有显式地进行创建,则默认创建一个root logger,应用默认的日志级别(WARN)、处理器Handler(StreamHandler将日志输出在标准输出设备上)和格式化器Formatter(默认的格式为ERROR:root:error message日志级别:实例名称:日志信息)。
创建方法:
logger=logging.getLogger(logger_name)
创建Logger实例后,使用以下方法进行日志级别设置,增加处理器Handler。
❑ logger.setLevel(logging.ERROR):设置日志级别为ERROR,即只有日志级别大于等于ERROR的日志才会输出。
❑ logger.addHandler(handler_name):为Logger实例增加一个处理器。
❑ logger.removeHandler(handler_name):为Logger实例删除一个处理器。
Logger可以包含一个或多个Handler和Filter,也就是说Logger与Handler或Fitler是一对多的关系;一个Logger实例可以新增多个Handler,一个Handler可以新增多个Formatter或多个Filter,而且日志级别将会继承。
2. Handler
Handler处理器常用类型有StreamHandler、FileHandler、NullHandler,点击查看参数使用说明。
StreamHandler创建方法: sh = logging.StreamHandler(stream=None)
创建StreamHandler后,设置日志级别,设置格式化器Formatter,增加或删除过滤器Filter,使用例子参考网上案例。
❑ sh.setLevel(logging.WARN):指定日志级别,低于WARN级别的日志将被忽略。
❑ sh.setFormatter(formatter_name):设置一个格式化器formatter。
❑ sh.addFilter(filter_name):增加一个过滤器,可以增加多个。
❑ sh.removeFilter(filter_name):删除一个过滤器。
FileHandler创建方法:
fh = logging.FileHandler(filename, mode='a', encoding=None, delay=False)
NullHandler创建方法:logging.NullHandler
3.Filter
Handler和Logger可以使用Filter来完成比级别更复杂的过滤。Filter基类只允许特定Logger层次以下的事件。例如,用’A.B’初始化的Filter允许Logger 'A.B'、 'A.B.C'、 'A. B.C.D'、 'A.B.D’等记录的事件,logger'A.BB'、'B.A.B’等就不行。如果用空字符串来初始化,所有的事件都接受。
创建方法:filter = logging.Filter(name='')
备注:A.B是啥?看不懂
4.Formatter
Formatter对象可以设置日志信息的规则、结构和内容,以及时间格式。
创建方法:formatter = logging.Formatter(fmt=None, datefmt=None)
其中,fmt是消息的格式化字符串,datefmt是日期字符串默认使用ISO8601日期格式%Y-%m-%d %H:%M:%S。
3. logging模块使用方法
1. import logging
第一次导入logging模块或使用reload函数重新导入logging模块,logging模块中的代码将被执行,这个过程中将产生logging日志系统的默认配置。
2. 自定义配置(可选)
logging.basicConfig(filename= 'logger.log', level=logging.ERROR)
logging.config.fileConfig("./logging.conf")
logging.config.dictConfig(config)
logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT)
logging模块支持配置方式:basicConfig、 dictConfig、fileConfig、listen。dictConfig通过一个字典配置Logger、Handler、Filter 、Formatter;fileConfig通过一个文件进行配置;listen则监听一个网络端口,通过接收网络数据来进行配置。
常用的format格式如下
3. 创建一个Logger对象实例
用logging模块的全局作用域中的getLogger函数来得到一个Logger对象实例。
logger=logging.getLogger(logger_name)
4. 用Logger对象实例记录日志
用Logger对象中的debug、info、error、warn、critical等方法记录日志信息。
logging.info('info message')
4. logging模块处理流程
1)判断日志的等级是否大于Logger对象的等级,如果大于,则往下执行,否则,流程结束。
2)产生日志。第一步,判断是否有异常,如果有,则添加异常信息。第二步,处理日志记录方法(如debug、info等)中的占位符,即一般的字符串格式化处理。
3)使用注册到Logger对象中的Filters进行过滤。如果有多个过滤器,则依次过滤;只要有一个过滤器返回假,则过滤结束,且该日志信息将丢弃,不再处理,而处理流程也至此结束。否则,处理流程往下执行。
4)在当前Logger对象中查找Handler,如果找不到任何Handler,则往上到该Logger对象的父Logger中查找;如果找到一个或多个Handler,则依次用Handler来处理日志信息。但在每个Handler处理日志信息过程中,会首先判断日志信息的等级是否大于该Handler的等级,如果大于,则往下执行(由Logger对象进入Handler对象中),否则,处理流程结束。
5)执行Handler对象中的filter方法,该方法会依次执行注册到该Handler对象中的Filter。如果有一个Filter判断该日志信息为假,则此后的所有Filter都不再执行,而直接将该日志信息丢弃,处理流程结束。
6)使用Formatter类格式化最终的输出结果。注:Formatter同“产生日志”第二步的字符串格式化不同,它会添加额外的信息,如日志产生的时间、产生日志的源代码所在的源文件的路径等。
7)真正地输出日志信息(到网络、文件、终端、邮件等)。至于输出到哪个目的地,由Handler的种类来决定。