为什么basicConfig中的python日志记录级别没有效果?

时间:2015-09-09 06:06:00

标签: python logging

import logging

# root logger
root = logging.getLogger()      # root
ch = logging.StreamHandler()
ch.setLevel(logging.WARN)
formatter = logging.Formatter('[root] %(levelname)s - %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)

# logging as child
c = logging.getLogger('mod')
c.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[mod] - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
c.addHandler(ch)

c.error('foo')
c.warning('foo')
c.info('foo')
c.debug('foo')

输出:

[mod] - ERROR - foo
[root] ERROR - foo
[mod] - WARNING - foo
[root] WARNING - foo
[mod] - INFO - foo
[mod] - DEBUG - foo

没关系。 root级别为WARN,因此不会打印root的INFODEBUG。 但是当我使用basicConfig时:

import logging

# config root logger
logging.basicConfig(level=logging.WARN, format='[root] %(levelname)s - %(message)s')

# logging as child
c = logging.getLogger('mod')
c.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[mod] - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
c.addHandler(ch)

c.error('foo')
c.warning('foo')
c.info('foo')
c.debug('foo')

输出:

[mod] - ERROR - foo
[root] ERROR - foo
[mod] - WARNING - foo
[root] WARNING - foo
[mod] - INFO - foo
[root] INFO - foo
[mod] - DEBUG - foo
[root] DEBUG - foo

basicConfig的级别为WARN,为什么可以打印根级别INFODEBUG

当我使用logging.info时,它会起作用。

1 个答案:

答案 0 :(得分:11)

您看到了这些[root]信息和调试消息,因为您对logging.basicConfig的调用会创建一个级别为NOTSET的根处理程序。级别为NOTSET的处理程序将输出它收到的任何消息(请参阅Handler.setLevel)。

>>> import logging
>>> logging.basicConfig(level=logging.WARN, format='[root] %(levelname)s - %(message)s')
>>> [handler.level == logging.NOTSET for handler in logging.getLogger().handlers]
[True]

这与您的第一个示例不同,因为在您的第一个示例中,您正在创建一个级别为WARN的根处理程序。

level=的{​​{1}}参数用于设置根 Logger 的级别,而不是任何根处理程序

记录消息传播

日志消息会传播到父Loggers,但不会考虑任何父Logger的级别。任何处理程序的级别决定了输出的内容"。

来自logging.Logger.propagate的文档:

  

消息直接传递给祖先记录器的处理程序 - 既不考虑有问题的祖先记录器的级别也不考虑过滤器。

那么什么是Logger.level?

Logger使用它的级别来决定是否将消息传播到其及其任何父记录器'处理程序。

如果Logger没有设置级别,那么它会询问其祖先Loggers的级别并使用它(参见logging.Logger.setLevel)。

因此,只有在您的子记录器上没有设置级别时,根记录器的级别才有意义。