在运行logging.basicConfig之前进行Python日志记录?
看来,如果您调用 logging.info()
BEFORE 运行 logging.basicConfig
,则 logging.basicConfig
调用没有任何效果。事实上,没有发生任何日志记录。
此行为记录在哪里?我实在不明白。
It appears that if you invoke logging.info()
BEFORE you run logging.basicConfig
, the logging.basicConfig
call doesn't have any effect. In fact, no logging occurs.
Where is this behavior documented? I don't really understand.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(7)
是的。
您已要求记录一些内容。因此,日志记录必须创建默认配置。一旦配置了日志记录...好吧...它就配置好了。
“配置记录器对象后,
以下方法创建日志
消息:“
此外,您可以阅读有关创建处理程序以防止虚假日志记录的信息。但这更多的是对不良实施的黑客攻击,而不是有用的技术。
这有一个技巧。
除了
logging.getLogger 之外,没有模块可以做任何事情()
全球级别的请求。只有
if __name__ == "__main__":
可以进行日志配置。
如果您在模块中进行全局级别的日志记录,那么您可以强制日志记录以伪造其默认配置。
不要在任何模块中全局执行logging.info
。如果您绝对认为模块中必须在全局级别拥有 logging.info
,那么您必须在执行导入之前配置日志记录。这会导致脚本看起来不舒服。
Carlos A. Ibarra 的回答原则上是正确的,但是该实现可能会中断,因为您正在迭代可能通过调用removeHandler() 来更改的列表。这是不安全的。
两个替代方案是:
while len(logging.root.handlers) > 0:
logging.root.removeHandler(logging.root.handlers[-1])
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)
或:
logging.root.handlers = []
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)
其中使用循环的这两个中的第一个是最安全的(因为可以在日志记录框架内显式调用处理程序的任何销毁代码)。尽管如此,这仍然是一个黑客行为,因为我们依赖logging.root.handlers作为一个列表。
这是上面的答案没有提到的难题之一......然后一切都会有意义:“根”记录器 - 如果您在记录之前调用logging.info(),则会使用它。 basicConfig(level=logging.DEBUG) -- 默认日志记录级别为 WARNING。
这就是为什么logging.info()和logging.debug()不做任何事情:因为你已经配置它们不,通过...嗯...不配置它们。
可能相关(这一点对我来说):当不调用 basicConfig 时,即使我将处理程序设置为 DEBUG 级别,我似乎也没有收到调试消息。经过一番绞尽脑汁后,我发现您还必须将自定义记录器的级别设置为“DEBUG”。如果您的记录器设置为 WARNING,则将处理程序设置为 DEBUG(单独)不会在 logger.info() 和 logger.debug() 上获得任何输出。
今天遇到了同样的问题,作为上述答案的替代方案,这是我的解决方案。
import logging
import sys
logging.debug('foo') # IRL, this call is from an imported module
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, force=True)
logging.info('bar') # without force=True, this is not printed to the console
以下是文档关于force<的内容/代码> 参数。
如果此关键字参数指定为 true,则任何现有处理程序
在携带之前,连接到根记录器的设备被移除并关闭
输出其他参数指定的配置。
@paul-kremer 给出的答案的更清晰版本是:
while len(logging.root.handlers):
logging.root.removeHandler(logging.root.handlers[-1])
注意:通常可以安全地假设logging.root.handlers 始终是一个列表(请参阅:https://github.com/python/cpython/blob/cebe9ee988837b292f2c571e194ed11e7cd4abbb/Lib/logging/初始化.py#L1253)
这就是我所做的。
我想记录到一个在配置文件中配置了名称的文件,并获取配置解析的调试日志。
TL;博士;这会记录到缓冲区中,直到配置记录器的所有内容都可用
# Log everything into a MemoryHandler until the real logger is ready.
# The MemoryHandler never flushes (flushLevel 100 is above CRITICAL) automatically but only on close.
# If the configuration was loaded successfully, the real logger is configured and set as target of the MemoryHandler
# before it gets flushed by closing.
# This means, that if the log gets to stdout, it is unfiltered by level
root_logger = logging.getLogger()
root_logger.setLevel(logging.NOTSET)
stdout_logging_handler = logging.StreamHandler(sys.stderr)
tmp_logging_handler = logging.handlers.MemoryHandler(1024 * 1024, 100, stdout_logging_handler)
root_logger.addHandler(tmp_logging_handler)
config: ApplicationConfig = ApplicationConfig.from_filename('config.ini')
# because the records are already logged, unwanted ones need to be removed
filtered_buffer = filter(lambda record: record.levelno >= config.main_config.log_level, tmp_logging_handler.buffer)
tmp_logging_handler.buffer = filtered_buffer
root_logger.removeHandler(tmp_logging_handler)
logging.basicConfig(filename=config.main_config.log_filename, level=config.main_config.log_level, filemode='wt')
logging_handler = root_logger.handlers[0]
tmp_logging_handler.setTarget(logging_handler)
tmp_logging_handler.close()
stdout_logging_handler.close()
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
您可以删除默认处理程序并重新配置日志记录,如下所示:
You can remove the default handlers and reconfigure logging like this: