**
python 标准输出重定向**
在python中,sys.stdout 和 sys.stderr 都是流对象,尽管他们只支持写入。 常量。这就意味着你可以给它们赋上新 值 — 任意其他流对象 — 来重定向他们的输出。
import sys
class RedirectStdoutTo:
def __init__(self, out_new):
self.out_new = out_new
def __enter__(self):
self.out_old = 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):
print('B')
print('C'
验证一下:
you@localhost:~/diveintopython3/examples$ python3
stdout.py
A
C
you@localhost:~/diveintopython3/examples$ cat out.log
B
你是否遇到了以下错误?
you@localhost:~/diveintopython3/examples$
python3 stdout.py
File "stdout.py", line 15
with open('out.log', mode='w',
encoding='utf‐8') as a_file,
RedirectStdoutTo(a_file):
^
SyntaxError: invalid syntax
如果是这样,你可能正在使用 Python 3.0。应该升 级到 Python 3.1。 Python 3.0 支持 with 语句,但是每个语句只能使用 一个上下文管理器。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 语句, 其中一个嵌套在另外一个的作用域(scope)里。“外层的”with 语 句你应该已经熟悉了:它打开一个使用 UTF‐8 编码的叫做 out.log 的文本文件用来写入,然后把返回的流对象赋给一个 叫做 a_file 的变量。但是,在此处,它并不是唯一显得古怪的 事情。
with RedirectStdoutTo(a_file):
as 子句(clause)到哪里去了?其实 with 语句并不一定需要 as 子句。就像你调用一个函数然后忽略其返回值一样,你也可以不把 with 语句的上下文环境赋给一个变量。在这种情况下,我们只关心 RedirectStdoutTo 上下文环境的边际效应(side effect)。
边际效应边际效应都是些什么呢?
RedirectStdoutTo类的内部结构。是一个用户自定义的上下文管理器(context manager)。任何类只要定义了两个特殊方法:code>enter()和__exit__()就可以变成上下文管理器。
class RedirectStdoutTo:
def __init__(self, out_new): ①
self.out_new = out_new
def __enter__(self): ②
self.out_old = sys.stdout
sys.stdout = self.out_new
def __exit__(self, *args): ③
sys.stdout = self.out_old
在实例被创建后__init__()方法马上被调用。它使用一个参数,即在上下文环境的生命周期内你想用做标准输出的流对象。这个方法只是把该流对象保存在一个实例变量里(instance variable)以使其他方法在后边能够使用到它。
enter()方法是一个特殊的类方法(special classmethod);在进入一个上下文环境时Python会调用它( 即 ,在with语句的开始处)。该方法把当前sys.stdout的值保存在self.out_old内,然后通过把self.out_new赋给sys.s放到一起:
print('A')
①
with open('out.log', mode='w', encoding='utf‐8') as
a_file, RedirectStdoutTo(a_file): ②
print('B')
③
print('C')
④
这条代码会输出到 IDE 的“交互式窗口(Interactive Window)”(或者终端,如果你从命令行运行这段脚本)。
这条with语句使用 逗号分隔的上下文环境列表 。这个列表就像一系列相互嵌套的with块。先列出的是“外层”的块;后列出的是“内层”的块。第一个上下文环境打开一个文件;第二个重定向sys.stdout到由第一个上下环境创建的流对象。
由于这个 print()函数在 with 语句创建的上下文环境里执行,所以它不会输出到屏幕;它会写入到文件 out.log。
with 语句块结束了。Python 告诉每一个上下文管理器完成他们应该在离开上下文环境时应该做的事。这些上下文环境形成一个后进先出的栈。当离开一个上下文环境的时候,第二个上下文环境将 sys.stdout 的值恢复到它的原来状态,然后第一个上下文环境关闭那个叫做 out.log 的文件。由于标准输出已经被恢复到原来的状态,再次调用 print()函数会马上输出到屏幕上。 重定向标准错误的原理跟这个完全一样,将 sys.stdout 替换为sys.stderr 即可