sys.stdout未被重新分配到sys.__stdout__

12

我刚开始学习Python,对这门语言还不够熟悉。其中一件事情是重新分配sys.stdout来改变print的默认输出。于是我写了这个测试:

import sys
sys.stdout = open('log.txt','a')
print('hey')
sys.stdout.close()
sys.stdout = sys.__stdout__
print('hi')

在文件中写入了'Hey',但是'hi'没有出现在任何地方。然而,以下代码按预期工作,'hey'被写入文件并且'hi'被打印到控制台输出:

import sys
sys.__stdout__ = sys.stdout
sys.stdout = open(r'C:\Users\Vincent\Documents\Python\log.txt','a')
print('hey')
sys.stdout.close()
sys.stdout = sys.__stdout__
print('hi')

简而言之,这只是一个不太重要的小问题,我只想知道为什么它不能按照应该的方式工作。我已经在Windows 7 Home Premium上试过,在v3.2.3的IDLE和pyscripter以及我的便携式Python v3.2.1上尝试过。


你怎么运行这个脚本?你没有说第一个 print 是否起作用了。当我在开头将一些其他变量分配给 sys.stdout 并将其改回来时,它可以工作最好编写代码来说明这一点,并描述它的输出。 - Piotr Dobrogost
3个回答

7
在IDLE中,sys.__stdout__是程序的原始标准输出 - 由于它不是控制台应用程序,所以它并没有输出到任何地方。换句话说,IDLE本身已经用它自己的控制台窗口替换了sys.stdout,因此如果你将自己的stdout替换为__stdout__,那么你就相当于倒退了两步。

2

我建议尝试此解决方法(根本不使用sys.__stdout__,因为您的环境可能会使sys.stdoutsys.__stdout__变成两个不同的对象):

old_stdout = sys.stdout
sys.stdout = open('log.txt','a')
print('hey')
sys.stdout.close()
sys.stdout = old_stdout

备份 sys.stdout 的引用似乎是最安全的方法。在另一个略有不同的情况下也起作用:Jupyter 笔记本的 stdout 重定向会落在终端中


0
这里有一个上下文管理器,可以为您备份sys.std<in|out|err>的旧状态,作为其他答案的补充。
个人而言,我在基于PyQt5的程序中使用它,其中标准输出被重定向到基于文本的小部件,只要应用程序正在运行。一旦应用程序关闭,输出将重新定向回我的IDE控制台。
import sys

class SysStdRedirection:
    """Any change done to `sys.std<in|out|err>` inside this context manager will
       be reverted upon exit."""

    def __init__(self):
        for x in ("stdin", "stdout", "stderr"):
            setattr(self, x, getattr(sys, x))

    def __enter__(self):
        pass

    def __exit__(self, error_type=None, value=None, traceback=None):
        for x in ("stdin", "stdout", "stderr"):
            setattr(sys, x, getattr(self, x))

使用方法:

with SysStdRedirection():
    sys.stdout = open('log.txt', 'a')
    print('hey')
    sys.stdout.close()
print('hi')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接