【问题标题】:Python logging calls showing on console even when redirecting stdout即使重定向标准输出,Python 日志记录调用也会显示在控制台上
【发布时间】:2017-09-13 14:56:30
【问题描述】:

我在装有 Python 3.6 的 Windows 7 机器上

我想知道为什么以下代码将记录器消息打印到控制台,即使记录器(或者更确切地说其父处理程序)配置为发送到标准输出并且标准输出被重定向到io.StringIO()。

import sys
import logging
from io import StringIO

logging.basicConfig(format='%(message)s', level=logging.DEBUG, stream=sys.stdout)

logger = logging.getLogger(__name__)

old_stdout = sys.stdout
sys.stdout = tmp = StringIO()
print('*** FIRST IN CODE : print')
logger.debug('*** SECOND IN CODE : logger')
sys.stdout = old_stdout
print(tmp.getvalue())

如果您注释掉这段代码中的最后一行 (print(tmp.getvalue())),您会看到 *** FIRST IN CODE : print 不再出现在控制台上,而 *** SECOND IN CODE : logger 仍然出现。

我尝试从basicConfig() 调用中删除stream=sys.stdout(在这种情况下,创建的StreamHandler 将默认为stderr)并重定向stderr,但结果与stderr 完全相同。

我还查看了StreamHandler 的代码,但也没有任何解释。

我了解到 Windows 上的 stdout/-err 重定向有一些怪癖。这是这里发生的事情还是我错过了什么?

【问题讨论】:

    标签: python python-3.x logging stdout io-redirection


    【解决方案1】:

    当您使用stream=sys.stdout 配置记录器时,记录器会获得对原始sys.stdout 值的引用,就像old_stdout 在后面的行中所做的那样。

    当您更改sys.stdout 时,您不会期望old_stdout 的值发生更改,对吧?那么为什么logger.stream(或其他任何名称)的值会发生变化?

    记录器没有注意到您已经更改了用于分配stream 参数的变量的值。为此,它需要将接收到的stream 参数与所有可能的来源(包括sys.stdout)进行比较,然后稍后检查该来源以查看它是否仍然与stream 参数匹配。这工作量太大,不符合为变量或参数赋值的一般预期。

    如果您想重定向输出,请在之前告诉程序的其他部分(例如您的记录器)将其输出发送到哪里。

    据记录器所知,您打算继续将日志记录到控制台,同时将其他输出发送到其他地方。

    【讨论】:

    • 这很有道理,我现在觉得有点愚蠢,因为这可能是我应该意识到的。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2011-05-19
    • 2016-09-24
    • 2018-12-28
    • 1970-01-01
    • 2010-11-19
    • 2019-03-15
    相关资源
    最近更新 更多