如何理解python中的sys.stdout和sys.stderr

how to understand sys.stdout and sys.stderr in python

我有以下简单的python代码。

1
2
3
4
5
6
7
8
stdout = sys.stdout
stderr = sys.stderr

try:
   # omited

finally:
  sys.stdout = stdout

搜索之后,我发现sys.stdin,sys.stdout和sys.stderr是与解释器的标准输入,标准输出和标准错误流相对应的文件对象。 所以,我的猜测是我们首先将sys.stdout和sys.stderr分配给变量stdout和stderr。 那么,即使try语句中有异常,我们也总是得到sys.stdout? 它是否正确? 我觉得我还是很困惑。 非常感谢您的时间和关注。


在普通的C程序中,默认情况下打开三个"文件":stdin,stdout和stderr。当您在C中输入和输出时,默认情况下它们来自stdin和stdout。但是,您也可以在代码需要文件的地方使用它们,或者将它们重新分配为新文件。

Python试图"模仿"C的这种行为。当你在Python中print()时,你的文本被写入Python的sys.stdout。当你执行input()时,它来自sys.stdin。例外写入sys.stderr

您可以重新分配这些变量,以便将代码的输出重定向到stdout以外的文件。这与shell重定向非常相似,如果您熟悉它的话。您可能会执行此类操作的原因是保留程序输出的日志或使代码"关闭",即不将输出发送到stdout。所以,在你的示例中:

1
2
3
4
5
6
7
8
9
10
stdout = sys.stdout

try:
    sys.stdout = open('file.txt', 'w')
    print('blah')
    # etc
finally:
    sys.stdout.close()  # close file.txt
    sys.stdout = stdout
    sys.stderr = stderr

此代码不会向控制台打印任何内容,但会将"blah"写入名为file.txt的文本文件中。为了使这类事情不那么容易出错,Python提供了sys.__stdin__sys.__stdout__,它总是保存sys.stdinsys.stdout的原始值。使用此代码可以使上述代码更简单:

1
2
3
4
5
6
7
try:
    sys.stdout = open('file.txt', 'w')
    print('blah')
    # etc
finally:
    sys.stdout.close()  # close file.txt
    sys.stdout = sys.__stdout__

Python同时具有stdout__stdout__的原因主要是为了方便,因此您不必创建变量来备份stdout

但是,我必须建议您不要重新分配stdout。以这种方式搞砸事情很容易!如果要保存代码的输出,可以使用shell重定向。如果您希望能够记录程序正在执行的操作,请参阅Python的日志记录模块。如果您希望代码更安静,请为您的函数指定一个quiet=False参数,以便在需要时将其关闭!很少有"真正的"需要重新分配stdout等等.Python允许你这样做,因为Python为程序员提供了很多控制,并期望他们负责。你可以做这样的事情,如果你真的想:

1
2
3
4
5
6
>>> import random
>>> random.random = lambda: 1
>>> random.random()
1
>>> random.random()
1