为什么根日志记录器接受子日志记录器的日志?

3 投票
1 回答
2219 浏览
提问于 2025-04-19 10:21

我不太明白根日志记录器和子日志记录器之间的关系:

import logging

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 1. SOME LOGGER
logger = logging.getLogger( 'logger' ) 
logger.setLevel(logging.INFO)

# 2. ROOT LOGGER
rootLogger = logging.getLogger()
rootLogger.setLevel( logging.CRITICAL )
fh = logging.FileHandler('root.log')
fh.setLevel( logging.DEBUG )
fh.setFormatter(formatter)
rootLogger.addHandler(fh)

#
logger.info( 'hello' ) 

最后一行 logger.info( 'hello' ) 应该是:

  • logger 接受,因为它设置了 logger.setLevel(logging.INFO)
  • rootLogger 拒绝,因为它设置了 rootLogger.setLevel( logging.CRITICAL )

但是在我的脚本结束时,我的文件 root.log 里却包含了 hello。为什么 CRITICAL 级别没有阻止 rootLogger 的消息呢?

1 个回答

6

这个问题发生的原因是,logger对象只继承了你给rootLogger分配的FileHandler对象,而没有继承日志级别。每个Logger对象都有自己的日志级别,所以它不会使用父级的日志级别。这意味着,当你通过logger进行日志记录时,它会先检查logger自己的日志级别(是INFO),然后再检查继承的FileHandler的级别(是DEBUG)——它不会检查父级的rootLogger对象的日志级别。因为loggerFileHandler的级别都设置为INFO或更高,所以你会看到'hello'被记录下来了。

如果你不想让logger继承rootLogger的处理器,可以把logger对象的propagate属性设置为'0':

logger = logging.getLogger( 'logger' ) 
logger.setLevel(logging.INFO)
logger.propagate = 0

如果你想让子logger继承父logger的日志级别,可以把子logger的级别设置为NOTSET

logger = logging.getLogger( 'logger' ) 
logger.setLevel(logging.NOTSET)

撰写回答