作者:吕嘉伟
在loging模块的应用中,经常使用的组件有loggers、handlers、formatters、filter。
Logger: 日志类,应用程序往往通过调用它提供的api来记录日志。
Handler: 对日志信息处理,可以将日志发送(保存)到不同的目标域中。
Formatter: 日志的格式化。
Filter:对日志内容或等级的过滤。
图1 日志输出的流程
如图1所示,打印一条日志处理流程是:
1. 用户代码调用打印日志函数(logging.info(), logging.debug()等);
2. 若希望打印的日志级别不够,则流程停止。否则进入步骤3;
3. 建立一个LogRecord对象,该对象表示一条日志,并判断本条日志是否被filter过滤掉,如果被过滤,流程停止,否则进入步骤4;
4. logger会将LogRecord传递到它所定义的handlers,进行处理,注意:handlers可以设置多个,会对一条日志进行多次处理。如果当前logger的propagate属性为0,则流程停止,否则进入步骤5;
5. 判断当前logger有无父logger,如果没有,则流程停止,否则设置当前logger为它的父logger,继续执行步骤4。
Handler的日志处理过程:
1. 如果当前LogRecord的级别小于handler所设置的LogLevel,则停止流程,否则进入步骤2。
2. 判断当前LogRecord是否被handler是否被它所设置的filter过滤,如果被过滤,则流程停止,否则日志被发送到最终的目的地。
logger
处理日志前,需要有一个logger对象,一般使用logging.getLogger(name=None)函数找到一个logger对象,当name所指定的logger不存在时,会自动创建一个该名称的对象,并保存在logging.manager的loggerDict中。
一般对logger的命名就是用模块名(__name__),目的是方便了解日志的产生位置,在这种情况下,需要设计自己的formatter和handler,或者使用parent logger提供的各种工具处理日志。表1展示了日志的等级及应用场景。表1 日志的等级及应用场景
Level | When it’s used |
DEBUG | Detailed information, typically of interest only when diagnosing problems. |
INFO | Confirmation that things are working as expected. |
WARNING(default) | An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR | Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL | A serious error, indicating that the program itself may be unable to continue running. |
Logger常用的方法:
Logger.setLevel() 配置logger关注的日志等级,只有大于等于该等级的日志才能被处理;
Logger.addHandler()、Logger.removeHandler() 添加、删除handler;
addFilter()、removeFilter() 添加、删除filter;
创建日志内容的方法:Logger.debug()、 Logger.info()、 Logger.warning()、Logger.error()、Logger.critical()。
handler
常用的日志处理器有SreamHandler和FileHandler。SreamHandler将日志输出到stream中,例如sys.stdout、sys.stderr,FileHandler将日志输出到文件中。
handler常用的方法:
setLevel() 、 setFormatter() 、 addFilter()、 removeFilter()filter
可以给handler和logger添加,可通过filter修改record的等级和内容,达到特殊目的。
使用方法:class InfoFilter(logging.Filter):
def filter(self, rec):
# rec为LogRecord对象
return rec.levelno == logging.INFO
logger.addFilter(InfoFilter())
使用logging的方式
1. 定义logger、handler等;
2. logging配置文件
举例:
import logging
import logging.config
logging.config.fileConfig('logging.conf')
# create logger
logger = logging.getLogger('simpleExample')
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')</span>
logging.conf:
[loggers]
keys=root,simpleExample
[handlers]
keys=consoleHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler
[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s</span>
3. logging配置字典
举例:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'loggers': {
'test': {
'handlers': ['console'],
'level': 'INFO',
},
},
}
logging.config.dictConfig(LOGGING)
logger = logging.getLogger('test')
logger.info('info message dict')
logger.warn('warn message dict')
logger.error('error message dict')
logger.critical('critical message dict')
参考文献:
https://docs.python.org/2/howto/logging.html
https://docs.python.org/3/library/logging.config.html#logging-config-dictschema