Python中的标准输入,输出与错误

标准输出和标准错误(通常缩写为stdoutstderr )是内置在所有类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.stdoutsys.stderr将它们的输出发送到相同的地方:Python ide,或者终端(如果是从命令行运行Python)。和标准输出一样,标准错误不会为您添加回车。如果你想要回车,你需要添加回车符。

sys.stdoutsys.stderr是流对象,但它们是只写的,尝试调用它们的read()方法将触发IOError

>>> import sys
>>> sys.stdout.read()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: not readable

重定向标准输出

sys.stdoutsys.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即可.

posted @ 2021-02-19 11:34  polyAI  阅读(898)  评论(0编辑  收藏  举报