python3 - 自定义记录器在没有 basicConfig 方法的情况下无法工作?

python3 - custom logger not working without basicConfig method?

我有这个代码:

    def __init__(self, log_level: str = None):
        self.log_level = log_level if log_level and log_level.lower() in ['debug', 'warning', 'info',
                                                                          'error'] else 'error'
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(getattr(logging, self.log_level.upper()))

我想创建没有配置的简单记录器。如果没有此行,此代码将无法正常工作: logging.basicConfig()

为什么?我真的无法理解。所以如果你尝试这样的事情:

self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.DEBUG)
self.logger.debug('test')

它不会打印任何东西。但这将:

logging.basicConfig()
self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.DEBUG)
self.logger.debug('test')

或者这个:

self.logger = logging.getLogger(__name__)
self.logger.setLevel(logging.DEBUG)
logging.debug("don't care")
self.logger.debug('test')

记录器必须定义处理程序。如果您使用 logging.getLogger(__name__) 创建记录器,则必须 addHandler。添加处理程序是 basicConfig 配置的一部分。

import logging

logger = logging.getLogger('test')
logger.addHandler(logging.StreamHandler())  # if you comment this line, logger will not print out message
logger.setLevel(logging.DEBUG)
logger.info('hi')

您可以为一个记录器添加多个句柄。此示例将打印 2 条消息(因为有两个 StreamHandler)。

import logging

logger = logging.getLogger('test')
logger.addHandler(logging.StreamHandler()) 
logger.addHandler(logging.StreamHandler()) 
logger.setLevel(logging.DEBUG)
logger.info('hi')

每个 hadler 可以有不同的格式化程序,不同的 logging_level,不同的输出。如果您想在所有级别的控制台日志中打印,但只记录关键和错误级别的消息,这将很有用。

导致这种行为的原因有很多。要理解的重要部分是 Python 有一个分层日志系统。您的记录器是 'root' 记录器的子项。每个记录器都可以独立配置。日志消息从子记录器传播到根记录器(除非 logger.propagate 设置为 False)。

logging.basicConfig 将为根记录器设置配置,包括处理程序,这是消息到达标准错误(或任何其他目的地)所必需的,前提是根记录器尚未配置处理程序.

>>> import logging
>>> logger = logging.getLogger(__name__)
>>> logger.setLevel(logging.DEBUG)
>>> root_logger = logger.root
>>> root_logger.handlers  # by default, there are no handlers
[]
>>> logger.debug('this wont show')
>>> logging.basicConfig()  # sets handler on the root logger
>>> root_logger.handlers
[<StreamHandler <stderr> (NOTSET)>]
>>> logger.debug('test')  # now this will go to stderr
DEBUG:__main__:test

我们还可以通过设置 logger.propagate = False 确认这是根记录器配置的结果,然后消息将不再到达 stderr。

>>> logger.propagate = False
>>> logger.debug('this wont show')

我们还可以看到我们的记录器没有自己的处理程序,但如果我们希望我们的记录器输出独立于根记录器(我们不再向其传播消息)的消息,我们可以添加它们。

>>> logger.handlers
[]
>>> logger.addHandler(logging.StreamHandler())
>>> logger.debug('test')
test

我们可以 re-enable 传播并看到两个记录器都将输出消息(每个记录器的每种格式)

>>> logger.propagate = True
>>> logger.debug('test')
test
DEBUG:__main__:test