标准输出和标准错误(通常缩写为stdout
和stderr
)是内置在所有类unix系统中的管道,包括Mac OS X和Linux。当你调用print()
函数时,你要打印的东西被发送到stdout
管道。当你的程序崩溃并打印出一个回溯信息时,它会转到stderr
管道。默认情况下,这两个管道都只是连接到工作的终端窗口;当你的程序打印一些东西时,你会在你的终端窗口中看到输出,当一个程序崩溃时,你也会在你的终端窗口中看到回溯。在图形Python Shell中,stdout
和stderr
管道默认为你的交互式窗口
。
for i in range(3):
... print('PapayaWhip') ①
PapayaWhip # 有换行
PapayaWhip
PapayaWhip
>>> import sys
>>> for i in range(3):
... l = sys.stdout.write('is the') ②
is theis theis the # 没有换行
>>> for i in range(3):
... l = sys.stderr.write('new black') ③
new blacknew blacknew black
① | print() 函数 |
---|---|
② | stdout 定义在sys 模块中,它是一个stream对象。调用它的write() 函数将打印出你给它的任何字符串,然后返回输出的长度。事实上,这就是print 函数真正做的事情;它在打印的字符串末尾添加一个回车,并调用sys.stdout.write 。 |
③ | 在最简单的情况下,sys.stdout 和sys.stderr 将它们的输出发送到相同的地方:Python ide,或者终端(如果是从命令行运行Python)。和标准输出一样,标准错误不会为您添加回车。如果你想要回车,你需要添加回车符。 |
sys.stdout
和sys.stderr
是流对象,但它们是只写的,尝试调用它们的read()
方法将触发IOError
。
>>> import sys
>>> sys.stdout.read()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: not readable
重定向标准输出
sys.stdout
和 sys.stderr
都是流对象,尽管它们只支持写入。但它们不是常数,而是变量。这意味着我们可以为它们分配一个新值——任何其他流对象——来重定向它们的输出。
#stdout.py
import sys
class RedirectStdoutTo:
def __init__(self, out_new):
self.out_new = out_new
def __enter__(self): # 进入上下文管理器执行
self.out_old = sys.stdout # backup sys.stdout
sys.stdout = self.out_new # 重定向
def __exit__(self, *args): # 退出上下文管理器执行
sys.stdout = self.out_old
print('A')
with open('out.log', mode='w', encoding='utf-8') as a_file, RedirectStdoutTo(a_file): # with, 此处接了两个上下文管理器
print('B')
print('C')
# 标准输出重定向到一个文件中去
Check this out:
you@localhost:~/diveintopython3/examples$ python3 stdout.py
A
C
you@localhost:~/diveintopython3/examples$ cat out.log
B
注意:Python 3.1之后单个
with
语句才支持多上下文管理器。
先瞅瞅最后一部分。
print('A')
with open('out.log', mode='w', encoding='utf-8') as a_file, RedirectStdoutTo(a_file):
print('B')
print('C')
这是一个复杂的with
语句,可以改写成更易读些:
with open('out.log', mode='w', encoding='utf-8') as a_file:
with RedirectStdoutTo(a_file):
print('B')
正如重写所示,实际上有两个 with
语句,其中一个嵌套在另一个的作用域中。外层的 with
语句现在应该很熟悉了:它会打开一个名为out.log
的utf-8
编码的文本文件,将流对象赋给一个名为a_file
的变量。但奇怪的地方在于:
with RedirectStdoutTo(a_file):
as
语句去哪了?with
语句实际上并不一定需要这个。就像你可以调用一个函数并忽略它的返回值一样,你可以有一个with
语句,并不把with
上下文赋值给一个变量。
看一下RedirectStdoutTo
类的内部。这个类是一个自定义上下文管理器。任何类都可以通过定义两个特殊方法: __enter__()
和__exit__()
)成为上下文管理器。
重定向标准错误方法是一样的了, sys.stderr
代替 sys.stdout
即可.