首页 > 解决方案 > 如何使用 Nullhandler 重定向外部模块的记录器警告?

问题描述

如果这个问题与 SO 上发布的其他问题相似,我深表歉意,但我已经尝试了许多给出的答案,但无法实现我想要做的事情。

我有一些调用外部模块的代码:

import trafilatura

# after obtaining article_html
text = trafilatura.extract(article_html, language=en)

这有时会在控制台上打印出警告,该警告来自 trafilatura 模块中的以下代码:

# at the top of the file
LOGGER = logging.getLogger(__name__)

# in the method that I'm calling
LOGGER.warning('HTML lang detection failed')

我不想将模块生成的此消息和其他消息直接打印到控制台,而是将它们存储在某个地方,以便我可以编辑消息并决定如何处理它们。(具体来说,我想以稍微修改的形式保存消息,但仅在特定情况下。)我没有在自己的代码中使用日志库。

我尝试了以下解决方案建议:

buf = io.StringIO()
with contextlib.redirect_stderr(buf):  # I also tried redirect_stdout
    text = trafilatura.extract(article_html, language=en)

buf = io.StringIO()    
sysout = sys.stdout
syserr = sys.stderr
sys.stdout = sys.stderr = buf
text = trafilatura.extract(article_html, language=en)
sys.stdout = sysout
sys.stderr = syserr

但是,在这两种情况下都buf保持为空,并且 trafilatura 仍将其日志消息打印到控制台。用其他调用(例如print("test"))测试上面的重定向,他们似乎可以很好地捕捉到那些,所以显然LOGGER.warning()从 trafilatura 只是没有打印到标准错误或标准输出?

我以为我可以为 trafilatura 设置不同的输出流目标LOGGER,但它使用的是 NullHandler,所以我既无法弄清楚它的流目标,也不知道如何更改它:

# from trafilatura's top-level __init__.py
logging.getLogger(__name__).addHandler(NullHandler())

有任何想法吗?提前致谢。

标签: pythonpython-3.xloggingio-redirection

解决方案


这里的想法是在 python 的标准日志库中工作。添加 NullHandler 实际上是添加记录器的库的标准推荐做法,因为如果不存在日志记录配置,它可以防止回退到 stderr。

这里可能发生的情况是,这些日志正在传播到根记录器,该记录器在其他地方附加了一些处理程序。您可以通过在代码中获取模块的记录器并将其设置为不传播来阻止这种情况:

# assuming that "trafilatura" is the __name__ of the module:
logger = logging.getLogger("trafilatura")
logger.propagate = False

推荐阅读