如何防止模块级日志功能破坏我的日志记录器?

1 投票
1 回答
744 浏览
提问于 2025-04-17 20:34

考虑一下这段代码,我是在 Python 2.7.6 版本下运行的:

import logging, sys

assert (__name__ not in logging.Logger.manager.loggerDict)
logger = logging.getLogger(__name__)
stdout_handler = logging.StreamHandler(sys.stdout)
logger.addHandler(stdout_handler)

logger.error("You'll see this once")
logging.debug("Imagine logging now happens in some other module, maybe via an import")
logger.error("You'll see this twice")
logger.propagate = False
logger.error("BUT this you'll only see once")

它输出了这个结果:

You'll see this once
You'll see this twice
ERROR:__main__:You'll see this twice
BUT this you'll only see once

问题似乎出在 logging.debug 调用了 logging.basicConfig:

上面这些模块级的便利函数,它们会把请求转发给根日志记录器,并调用 basicConfig(),以确保至少有一个处理器可用 (来源)

我想从中得出的简单规则是“不要使用模块级的便利函数”,但令人担心的是,任何使用这些函数(或者调用 logging.basicConfig)的模块都会影响我其他的日志记录。所以我想的教训可能是“对于父级是根日志记录器的日志记录器,始终使用 propagate=False”,但这样感觉不太对——propagate 默认应该是 True 是有原因的。有没有更好的办法呢?

1 个回答

2

可怕的是,任何使用这些函数(或者调用 logging.basicConfig 的模块)都会导致我其他的日志功能出问题。

是的,确实有可能,但这些模块其实没有遵循好的编程规范(这些规范是有文档说明的)。实际上,在你上面的代码片段中,你的做法是错误的——除了 NullHandler,不应该在主脚本的 if __name__ == '__main__ 之外去给日志器添加处理器。导入代码时不应该有副作用。

模块级别的便利函数适合用在短小的脚本、简单的使用场景,以及刚开始接触日志功能的人。它们并不适合在日志需求更复杂的情况下使用。

撰写回答