Python中的標准輸出和錯誤輸出由sys模塊的stdout、stderr對象負責,所有print語句以及相關的錯誤信息輸出如果要重定向,只需要創建一個類似文件IO的類並將該類的實例替換sys模塊的stdout、stderr對象即可。
具體來說,分如下幾步完成:
-
備份標准輸出sys.stdout、stderr對象,以便恢復或做其他處理;
-
構建一個支持類似文件io的類
Python判斷對象是否支持文件IO,是個典型的鴨子類型處理方式,就是看對象是否實現了讀寫方法,由於標准輸出無需讀只需寫,因此只要實現了write方法即可,在對應write方法對捕獲輸出信息進行處理,如輸出到特定文件或圖形化窗口 -
使用該類似文件io的類創建一個對象,將其賦值給sys.stdout。
案例:
import sys
class myStdout():
def __init__(self):
self.stdoutbak = sys.stdout
self.stderrbak = sys.stderr
sys.stdout = self
sys.stderr = self
def write(self,info):
#info信息即標准輸出sys.stdout和sys.stderr接收到的輸出信息
str = info.rstrip("\r\n")
if len(str):self.processInfo(str) #對輸出信息進行處理的方法
def processInfo(self,info):
self.stdoutbak.write("標准輸出接收到消息:"+info+"\n") #可以將信息再輸出到原有標准輸出,在定位問題時比較有用
def restoreStd(self):
print("准備恢復標准輸出")
sys.stdout = self.stdoutbak
sys.stderr = self.stderrbak
print("恢復標准輸出完成")
def __del__(self):
self.restoreStd()
print("主程序開始運行,創建標准輸出替代對象....")
mystd = myStdout()
print("標准輸出替代對象創建完成,准備銷毀該替代對象")
#mystd.restoreStd()
del mystd
print("主程序結束")
運行截圖:

可以看到,由於上述代碼恢復標准輸出是從析構方法調用的,由於Python銷毀對象的內在處理機制導致析構方法不會在執行del后即執行,且析構方法執行存在不可控因素,導致主程序退出后析構方法未調用,直到執行完成后再次在輸出界面按回車鍵才輸出信息,並且這種析構處理過程帶有一定的隨機性。因此最好顯示的調用恢復標准輸出的restoreStd方法,且不一定要執行del語句,這樣更可控。
下面是調整的主程序代碼:
print("主程序開始運行,創建標准輸出替代對象....")
mystd = myStdout()
print("標准輸出替代對象創建完成,准備銷毀該替代對象")
mystd.restoreStd()
#del mystd
print("主程序結束")
執行后結果如下:

從上述過程可以明顯看到標准輸出重定向捕獲成功了。

