標准輸出和標准錯誤(通常縮寫為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
即可.