Python日志调用即使在重定向stdout时也会显示在控制台上

Python日志调用即使在重定向stdout时也会显示在控制台上,python,python-3.x,logging,stdout,io-redirection,Python,Python 3.x,Logging,Stdout,Io Redirection,我在一台装有Python3.6的Windows7机器上 我想知道为什么下面的代码会将记录器消息打印到控制台,即使记录器(或者更确切地说它的父处理器)被配置为发送到stdout,并且stdout被重定向到io.StringIO() 如果注释掉此代码中的最后一行(print(tmp.getvalue())),您将看到***代码中的第一位:print不再显示在控制台上,而***代码中的第二位:logger仍然显示 我已经尝试从basicConfig()调用中删除stream=sys.stdout(在这

我在一台装有Python3.6的Windows7机器上

我想知道为什么下面的代码会将记录器消息打印到控制台,即使记录器(或者更确切地说它的父处理器)被配置为发送到stdout,并且stdout被重定向到
io.StringIO()

如果注释掉此代码中的最后一行(
print(tmp.getvalue())
),您将看到
***代码中的第一位:print
不再显示在控制台上,而
***代码中的第二位:logger
仍然显示

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

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


我已经读到Windows上的stdout/-err重定向有一些怪癖。这就是这里发生的事情还是我遗漏了什么?

当您使用
stream=sys.stdout
配置记录器时,记录器将获得原始
sys.stdout
值的引用,就像后面一行中的
old\u stdout
一样

当您更改
sys.stdout
时,您不希望
old\u stdout
的值发生更改,对吗?那么为什么
logger.stream
(或者它真正的名称)的值应该改变呢

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

如果要重定向输出,请在告诉程序的其他部分(如记录器)将输出发送到何处之前进行重定向


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

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

当您更改
sys.stdout
时,您不希望
old\u stdout
的值发生更改,对吗?那么为什么
logger.stream
(或者它真正的名称)的值应该改变呢

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

如果要重定向输出,请在告诉程序的其他部分(如记录器)将输出发送到何处之前进行重定向


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

这很有道理,我现在觉得有点愚蠢,因为这可能是我应该意识到的。非常感谢。这很有道理,我现在觉得有点愚蠢,因为这可能是我应该意识到的。非常感谢你。
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())