python logging模块
1.logging模块提供了四个组件
logger:日志类,有两个功能
1)配置日志的等级,处理器handler,过滤器filter
logger.setLevel(logging.INFO)
logger.addHandler(handler)
logger.addFilter(filter)
2)写日志
logger.info()
handler:处理器类,实际写日志的类
常用的处理器有StreamHandler和FileHandler
StreamHandler将日志输出到stream,如sys.stdout,sys.stderr
FileHandler将日志输出到文件
处理器类可以配置自己的等级,过滤器
一个logger可以配置多个处理器类
filter:过滤器类,过滤日志等级,内容
使用示例如下:
class InfoFilter(logging.Filter):
def filter(self,rec):
reurn rec.levelno==logging.INFO
logger.addFilter(InfoFilter())
formatter:内容格式化类,格式化输出的内容
格式化配置,使用%(<dict key>)s的形式,具体有哪些关键字,可以参照官网的介绍。
使用示例如下:
fmt='%(asctime)s - %(filename)s:%(lineno)s - %(name)s - %(message)s'
formatter=logging.Formatter(fmt)
handler.setFormatter(formatter)
2.logger对象
使用logging.getLogger(name=None)函数找到一个logger对象,当name指定的logger不存在时,会自动创建一个该名称的对象,保存在logging.manage的loggerDict中。
3.logging日志输出流程
logger输出日志的流程:
1)用户代码调用打印日志函数(logging.info(),logging.debug()等)
2)若希望打印的日志级别不够,则流程停止。否则进入步骤3
3)建立一个LogRecord对象,该对象代表打印的日志
4)判断这条日志是否被filter过滤掉,如果被过滤,流程停止。否则进入步骤5
5)logger将LogRecord传递到它定义的handlers,进行处理
6)判断当前logger的propagate属性,为0,则流程停止,否则进入步骤7
7)判断当前logger有无父logger,如果没有,流程停止,否则设置当前logger为它的父logger,继续执行步骤5
注:logger对象是有继承关系的,如名为a.b,a.c的logger都是名为a的子logger,并且所有的logger对象都继承自root,如果子对象没有添加handler等配置,会从父对象继承,这样可以通过继承关系来复用配置。
handler处理日志的过程:
1)如果当前LogRecord的级别小于handler所设置的LogLevel,则停止流程,否则进入步骤2
2)判断当前LogRecord是否被handler设置的filter过滤,如果被过滤,流程停止,否则日志输出到最终目的地。
4.logging使用示例
logging有三种配置方式
1)代码定义logger,handler等
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging import logging.config handler = logging.StreamHandler() fmt = '%(asctime)s - %(filename)s:%(lineno)s - %(name)s - %(message)s' formatter = logging.Formatter(fmt) # 实例化formatter handler.setFormatter(formatter) # 为handler添加formatter logger = logging.getLogger('tst') # 获取名为tst的logger logger.addHandler(handler) # 为logger添加handler logger.setLevel(logging.DEBUG) logger.info('first info message') logger.debug('first debug message')
2)logging配置文件
loggin.conf采用了模式匹配的方式进行配置,正则表达式是r'^[(.*)]$',从而匹配出所有的组件。对于同一个组件具有多个实例的情况使用逗号‘,’进行分隔。对于一个实例的配置采用componentName_instanceName配置块。使用这种方式还是蛮简单的。
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
#!/usr/bin/env python # -*- coding: utf-8 -*- 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')
3)logging配置字典
#!/usr/bin/env python # -*- coding: utf-8 -*- import logging import logging.config LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'loggers': { 'test': { 'handlers': ['console'], 'level': 'ERROR', }, }, } 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')