Python日志根记录器即使我将级别设置为INFO也不显示信息

20

我创建了以下脚本。 你们中的任何人能解释一下为什么输出结果是像下面所示的吗?

源代码

import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

print('debug', logger.isEnabledFor(logging.DEBUG))
print('info', logger.isEnabledFor(logging.INFO))
print('warning', logger.isEnabledFor(logging.WARNING))
print('error', logger.isEnabledFor(logging.ERROR))

logger.debug('debug')
logger.info('info')
logger.warning('warning')
logger.error('error')

logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')

输出

debug True
info True
warning True
error True
warning
error
DEBUG:root:debug
INFO:root:info
WARNING:root:warning
ERROR:root:error

具体来说

  1. 这里的logger.infologging.info有什么区别

  2. 为什么logger.isEnabledFor(logging.DEBUG)True,但logger.debug('debug')没有显示任何内容

  3. 为什么logger.info没有输出,但logging.info

2个回答

13

需要澄清几件事情:

  1. 根记录器的默认日志级别为WARNING
  2. 如果没有设置任何处理程序或格式化程序,则不会初始化根记录器:

    >>> import logging
    >>> logging.root.handlers
    []
    

好的,但你发现了问题:当日志记录级别设置为DEBUG时,根记录器未按预期工作。 调试消息被忽略。 相同的未配置的根记录器会正常输出警告消息。 为什么呢?

请记住,我们目前没有任何处理程序用于根记录器。 但是查看代码,我们可以看到:

    if (found == 0):
        if lastResort:
            if record.levelno >= lastResort.level:
                lastResort.handle(record)
        elif raiseExceptions and not self.manager.emittedNoHandlerWarning:
            sys.stderr.write("No handlers could be found for logger"
                             " \"%s\"\n" % self.name)
            self.manager.emittedNoHandlerWarning = True
这意味着,如果没有找到处理程序,我们有一个备用的“lastResort”。您可以参考“lastResort”的定义,它使用日志级别“WARNING”进行初始化。同时,调试消息没有这个备份,因此当没有设置处理程序时,它们会被忽略。
针对你的问题:
1. 当 getLogger() 没有参数时,这两个记录器是相同的,因为返回根记录器。 2. 请参见下文:

Logger.isEnabledFor(lvl)

指示此记录器是否会处理严重性级别为lvl的消息。此方法首先检查由 logging.disable(lvl) 设置的模块级别,然后检查记录器的有效级别,该级别由 getEffectiveLevel() 确定。

3. 在 logging 模块中调用任何日志函数都将使用 basicConfig() 初始化根记录器,并添加默认处理程序,以便随后对记录器的调用也能正常工作。
您应该使用logging.basicConfig()来设置根记录器的默认处理程序,这样消息将根据记录器级别和消息级别输出。

谢谢@Ares Ou。我明白了你对logger行为的看法。您能否再解释一下为什么如果logging.debuglogger.debug是相同的东西,那么logging.debug会起作用呢? - doraemon
它们都是“根记录器”,但当您调用logging.debug时,会调用basicConfig(),这使它们有所不同。如果在上面的代码之后调用logger.debug('debug'),则会看到输出DEBUG:root:debug,然后您将会明白。 - Cheney
你的意思是,如果还没有初始化根记录器,那么对 logging.log 的任何调用都会使用 basicConfig() 来初始化它? - doraemon
不行!你可以阅读logging.[log|debug|...]basicConfig()只有在root没有handler时才会被调用。 - Cheney
如果我理解正确,记录器实例正在处理INFO和DEBUG,但(默认)处理程序没有?也许您可以澄清记录器级别和处理程序级别之间的区别。 - Jacktose

2

getLogger如果添加了name参数,则创建Logger类的实例。否则,它将返回根记录器。因此,在这种情况下,程序使用常用的日志记录器作为logging.debuglogging.infologging.warninglogging.info函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接