我试图将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?
答案 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'] = ...
希望这有助于增加一点清晰度!