为什么我不能使用"从sys import stdout"重定向STDOUT?

时间:2018-04-12 01:47:14

标签: python stdout python-import sys

我试图将python脚本的STDOUT重定向到文件。

如果从 sys 导入STDOUT,则脚本的输出会重定向到文件:

from sys import stdout
stdout = open("text", "w")
print("Hello")

但是,如果我导入 sys并使用sys.stdout,则会成功重定向脚本的输出:

import sys
sys.stdout = open("text", "w")
print("Hello")

这是为什么?根据{{​​3}},"导入X"之间的唯一区别和#34;来自X import Y"是绑定的名称。这如何影响stdout?

4 个答案:

答案 0 :(得分:4)

是的,唯一的区别是名称Y绑定到X.Y

无论哪种方式,将Y绑定到其他内容都不会影响X中的任何内容。

如果它更容易,请考虑这个并行:

>>> y = 2
>>> x = y
>>> x = 3

您是否希望将y更改为3?当然不是。但这与你正在做的完全一样。

如果仍然不清楚,让我们分解那些import实际做的事情。

当你import sys时,它相当于:

sys.modules['sys'] = __import__('sys')
sys = sys.modules['sys']
sys.stdout = open(text, "w")

但是from sys import stdout

sys.modules['sys'] = __import__('sys')
stdout = sys.modules['sys'].stdout
stdout = open(text, "w")

答案 1 :(得分:1)

它与:

相同
x = some_object.some_attr
x = open(...)

在这种情况下,您不会更改some_object.some_attr。你只需要分配一个本地值。

当您使用sys.stdout = ...时,您实际上正在更新标准输出。

答案 2 :(得分:1)

我这样做的方法是创建一个上下文管理器。

@contextmanager
def suppress_stdout():
    with open(os.devnull, 'w') as devnull:
        old_stdout = sys.stdout
        old_stderr = sys.stderr
        sys.stdout = devnull
        try:
            yield
        finally:
            sys.stdout = old_stdout
            sys.stderr = old_stderr

然后当我想在某个命令上抑制stdout时:

with suppress_stdout():
    # suppressed commands    

答案 3 :(得分:0)

你可以节省一些精力,用这个小技巧为自己赢得一些“Pythonic”积分:

import sys
print('hello', file=sys.stdout)

当然,默认情况下print已经转到sys.stdout,所以也许我错过了一些东西。我不确定open('text', 'w')发生了什么,但如果你这样做可能没有必要:)

在回答有关变量赋值影响的问题时,当您对变量使用=运算符时,实际上是将其赋值给范围字典中的值(在本例中为globals

因此,当您导入sys时,会在sys字典中导入globals

所以globals看起来像,

{...,
'sys': <module 'sys' (built-in)>}

您可以将模块本身视为字典。所以当你做sys.stdout=时...就像做globals()['sys'].__dict__['stdout'] =...

一样

当您导入stdout时,globals看起来像是:

{...,
'stdout': <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>}

因此当你执行stdout=...时,你真的直接替换了字典中的那个键:

globals()['stdout'] = ...

希望这有助于增加一点清晰度!