在运行logging.basicConfig之前如何使用Python日志?

58 投票
7 回答
25686 浏览
提问于 2025-04-15 17:16

看起来如果你在运行 logging.basicConfig 之前就调用了 logging.info(),那么 logging.basicConfig 的设置就不会起作用。实际上,这时候不会有任何日志记录。

这个行为在哪里有说明呢?我不是很明白。

7 个回答

11

卡洛斯·A·伊巴拉的这个回答原则上是对的,不过他的实现可能会出问题,因为你在遍历一个可能会被调用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是一个列表。

13

是的。

你想要记录一些信息,所以记录功能需要先设置一个默认的配置。一旦设置好了记录功能……嗯……就算是配置完成了。

“配置好记录器对象后,下面的方法可以用来创建日志信息。”

另外,你可以了解一下如何创建处理器,以避免不必要的日志记录。但这更多是针对糟糕实现的一个小技巧,而不是一个实用的技术。

这里有个小窍门。

  1. 没有任何模块可以在全局范围内做其他事情,除了调用 logging.getLogger()

  2. 只有 if __name__ == "__main__": 这一部分可以进行日志配置。

如果你在模块的全局范围内进行日志记录,那么可能会强制日志系统生成它的默认配置。

不要在任何模块的全局范围内使用 logging.info。如果你真的觉得必须在模块的全局范围内使用 logging.info,那么你必须在导入其他内容之前先配置日志。这会导致脚本看起来不太好。

56

你可以像这样去掉默认的处理程序,并重新设置日志记录:

# if someone tried to log something before basicConfig is called, Python creates a default handler that
# goes to the console and will ignore further basicConfig calls. Remove the handler if there is one.
root = logging.getLogger()
if root.handlers:
    for handler in root.handlers:
        root.removeHandler(handler)
logging.basicConfig(format='%(asctime)s %(message)s',level=logging.DEBUG)

撰写回答