调用`logging`会干扰其他模块

时间:2021-01-12 00:39:45

标签: python python-3.x

假设我有以下 a.py 调用 b.py

b.py

import logging
  
logging.info('11111 in b')     

def do():                      
    logging.info('2222222 in b')  

a.py

import logging
import sys
import b

logging.basicConfig(stream=sys.stdout, level=logging.INFO)
logging.info('11111111 in a')
b.do()

当我执行 a.py 时,没有记录到 stdout,但是当我从 logging.info('11111 in b') 中注释掉 b.py 时,如下所示:

b.py

import logging
  
# logging.info('11111 in b')     

def do():                      
    logging.info('2222222 in b')  

我可以看到日志输出:

INFO:root:11111111 in a
INFO:root:2222222 in b

很明显,注释掉的行与此有关,但我原以为 basicConfig() 会在导入 b 模块后直接设置一些内容,但事实并非如此。

有人可以解释一下这里发生了什么吗?

2 个答案:

答案 0 :(得分:2)

导入语句 import b 在日志系统被配置之前触发了一个日志事件。当使用未配置的日志系统记录事件时,它会使用默认配置自动配置:stderr 上级别为 WARNING 的流处理程序。

如果根记录器已经配置了处理程序,则后续的 basicConfig 调用不会执行任何操作。因此,INFO 级别的事件被过滤掉,因为根记录器配置了一个处理程序,其阈值为 WARNING。

正确的解决方案是确保在配置日志系统之前不会记录事件。通常这意味着避免日志事件或在全局(模块级别)范围内执行任何工作。

但是,since Python 3.8 有一种解决方法可以强制重新配置日志记录系统:

logging.basicConfig(stream=sys.stdout, level=logging.INFO, force=True)

在较旧的 Python 版本中,您可以手动清除根日志记录处理程序:

del logging.getLogger().handlers[:]
logging.basicConfig(stream=sys.stdout, level=logging.INFO)

答案 1 :(得分:0)

我怀疑这与输出的配置方式有关。我不认为在 a.py 中设置它会为两个文件设置它,有点像你必须在两个文件中导入日志,否则会出错。

如果您将 basicConfig 行添加到 b.py,那么您可以保留您的 logging.info('11111 in b') 并看到它打印出来。