关于python中logging模块的那些坑
Python中内置库的Logging模块是非常好用的日志模块,可以用来追踪代码运行时候的事件并且将其记录成为日志文件。logging模块一般分为5个严重性级别:debug
、info
、warning
、error
、critical
。并且可以按照开发者的需要自定义记录的级别,默认为warning
级别。本文主要是记录下自己在使用logging模块后踩中的一些坑。
第一个坑:
先看一个例子
import logging
log1 = logging.getLogger('mylog')
log1.setLevel(logging.DEBUG)
log2 = logging.getLogger('mylog')
log2.setLevel(logging.INFO)
fh = logging.FileHandler('test.log')
ch = logging.StreamHandler()
log1.addHandler(fh)
log1.addHandler(ch)
log2.addHandler(fh)
log2.addHandler(ch)
log1.debug('log1 debug message')
log1.info('log1 info message')
log1.warning('log1 warning message')
log1.error('log1 error message')
log1.critical('log1 critical message')
log2.debug('log2 debug message')
log2.info('log2 info message')
log2.warning('log2 warning message')
log2.error('log2 error message')
log2.critical('log2 critical message')
在上面的例子中,定义了log1与log2两个实例,此时并且赋予了输出到文本与输出到控制台的属性,log1设置为从debug
级别开始输出,log2设置为从info
级别开始输出。本应该log1输出5条,log2输出4条的,但是实际情况并不是这样。
真实输出为:
log1 info message
log1 warning message
log1 error message
log1 critical message
log2 info message
log2 warning message
log2 error message
log2 critical message
明明已经将log1的输出级别调整为debug
了,却是从info
级别开始输出的,这是为什么呢?
问题就出在定义log1与log2的用户上,logging模块中取名是唯一的,mylog对象都是root的子对象,在logging模块中就看来log1与log2按照同一种对象了。因此log2覆盖了log1的debug
级别从而导致log1设置的级别失效了。
第二个坑:
再看一个例子:
import logging
logger = logging.getLogger()
log1 = logging.getLogger('mylog')
log1.setLevel(logging.DEBUG)
fh = logging.FileHandler('test.log')
ch = logging.StreamHandler()
logger.addHandler(fh)
logger.addHandler(ch)
log1.addHandler(fh)
log1.addHandler(ch)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
log1.debug('log1 debug message')
log1.info('log1 info message')
log1.warning('log1 warning message')
log1.error('log1 error message')
log1.critical('log1 critical message')
按照上面来看,应该logger会打印默认的warning
级别以上的信息,log1会打印我们指定的debug
以上的信息,然而情况并不是这样。实际输出为:
logger warning message
logger error message
logger critical message
log1 debug message
log1 debug message
log1 info message
log1 info message
log1 warning message
log1 warning message
log1 error message
log1 error message
log1 critical message
log1 critical message
我们可以看到logger打印的是正确的,但是log1突然超级加倍了,所有的都打印了两遍,这是为什么呢?
经过查阅官方文档和其他博客的经验,我了解到了更深层次的用户逻辑。
logger我们创建是使用的根用户,log1是我们创建的mylog用户,在logging模块中,子用户每次打印时都会去调用父用户,也就是说每次log1打印的时候都会连带着logger来打印,这就是为什么log1打印了两次。