正如logger.setLevel doc所说:
创建记录器时,级别设置为NOTSET(当记录器是根记录器时会导致处理所有消息,或者当记录器是非root记录器时委托给父级)。请注意,根记录器的创建级别为WARNING。
所以我想如果我用级别NOTSET创建一个根记录器,将显示调试和信息日志。
代码使用basicConfig将根记录器的级别设置为NOTSET是正确的:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
logging.basicConfig(level=logging.NOTSET)
log = logging.getLogger()
log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')
,输出为:
DEBUG:root:debug
INFO:root:info
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical
但是,如果我创建一个根记录器,并向其添加NOTSET级别的处理程序,例如:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
log = logging.getLogger()
hd = logging.StreamHandler()
hd.setLevel(logging.NOTSET)
log.addHandler(hd)
log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')
输出是:
warning
error
critical
但我认为它也会输出调试和信息消息。
答案 0 :(得分:5)
好的,我误解了文档中的Logger's level
和Handler's Level
:
setLevel()方法与logger对象一样,指定将分派到适当目标的最低严重性。为什么有两个setLevel()方法?记录器中设置的级别确定将传递给其处理程序的消息的严重性。每个处理程序中设置的级别确定处理程序将发送哪些消息。
如果我将代码更改为此,则可以:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
log = logging.getLogger()
log.setLevel(logging.NOTSET) # Set Logger's level to NOTSET, default is WARNING
#print "Logger's Level: ", log.level
hd = logging.StreamHandler()
hd.setLevel(logging.NOTSET)
#print "Handler's Level: ", hd.level
log.addHandler(hd)
log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')
答案 1 :(得分:0)
让我们以示例的方式说明,在创建记录器的具体实例时,UNSET不会做任何事情(出于某种神秘的原因):
def logging_unset_level():
"""My sample logger explaining UNSET level
Resources:
- https://stackoverflow.com/questions/21494468/about-notset-in-python-logging
- https://www.youtube.com/watch?v=jxmzY9soFXg&t=468s
- https://github.com/CoreyMSchafer/code_snippets/tree/master/Logging-Advanced
"""
import logging
logger = logging.getLogger(__name__) # loggers are created in hierarchy using dot notation, thus __name__ ensures no name collisions.
print(f'DEFAULT VALUE: logger.level = {logger.level}')
file_handler = logging.FileHandler(filename='my_log.log')
log_format = "{asctime}:{levelname}:{lineno}:{name}:{message}" # see for logrecord attributes https://docs.python.org/3/library/logging.html#logrecord-attributes
formatter = logging.Formatter(fmt=log_format, style='{')
file_handler.setFormatter(fmt=formatter)
stdout_stream_handler = logging.StreamHandler(stream=sys.stdout)
stdout_stream_handler.setLevel(logging.INFO)
log_format = "{name}:{levelname}:-> {message}" # see for logrecord attributes https://docs.python.org/3/library/logging.html#logrecord-attributes
formatter = logging.Formatter(fmt=log_format, style='{')
stdout_stream_handler.setFormatter(fmt=formatter)
logger.addHandler(hdlr=file_handler)
logger.addHandler(hdlr=stdout_stream_handler)
logger.log(logging.NOTSET, 'notset')
logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')
logger.critical('critical')
屏幕输出为:
DEFAULT VALUE: logger.level = 0
__main__:WARNING:-> warning
__main__:ERROR:-> error
__main__:CRITICAL:-> critical
stdout
的输出是:
2020-04-15 17:00:38,384:WARNING:200:__main__:warning
2020-04-15 17:00:38,384:ERROR:201:__main__:error
2020-04-15 17:00:38,384:CRITICAL:202:__main__:critical
如问题正文所预期的那样,实例化记录器时,其设置为UNSET
。如果您出于某种原因使用基本配置,则它确实可以正常工作,因为文档暗示在实例化记录程序时,应该从UNSET到更高版本的所有记录 BUT,但此设置仅会使错误消息出于某些原因起作用(查找给我一个参考!)。
好吧,现在,如果再次运行它,但又增加了顶级记录器的级别,一切都会按预期运行(未设置的除外):
logger.setLevel(logging.DEBUG)
stdout的输出(出于教学原因,在我的示例中,stdout处理程序的级别为INFO,与文件处理程序不同,试图显示顶级记录器对.level值的继承)。
DEFAULT VALUE: logger.level = 10
__main__:INFO:-> info
__main__:WARNING:-> warning
__main__:ERROR:-> error
__main__:CRITICAL:-> critical
和记录器文件my_log.log
的输出(这确实输出调试语句!:D):
2020-04-15 17:05:58,782:DEBUG:198:__main__:debug
2020-04-15 17:05:58,784:INFO:199:__main__:info
2020-04-15 17:05:58,784:WARNING:200:__main__:warning
2020-04-15 17:05:58,784:ERROR:201:__main__:error
2020-04-15 17:05:58,784:CRITICAL:202:__main__:critica
符合预期。它继承了顶层记录器级别,因此可以打印从调试级别开始的所有内容。