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的INFO
和DEBUG
。
但是当我使用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
,为什么可以打印根级别INFO
和DEBUG
?
当我使用logging.info
时,它会起作用。
答案 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使用它的级别来决定是否将消息传播到其及其任何父记录器'处理程序。
如果Logger没有设置级别,那么它会询问其祖先Loggers的级别并使用它(参见logging.Logger.setLevel
)。
因此,只有在您的子记录器上没有设置级别时,根记录器的级别才有意义。