2017-08-02 101 views
3

我想在Python腳本的末尾捕獲控制檯輸出。也就是說,我想要像往常一樣打印到控制檯,並且在執行結束時將控制檯輸出保存到文件中。將stdout重定向到日誌文件,同時仍然打印到stdout?

我已經看到了各種相關的做題123雖然他們或者簡單重定向輸出,而不是顯示它或使用logging。從我通過閱讀loggingdoc可知,您只能記錄您編寫的代碼的輸出。

上面所有鏈接的問題是從您沒有寫入的代碼輸出的控制檯輸出到控制檯。 我希望程序的整個控制檯輸出在執行結束時

我的第一反應是沿着

logFile = open('LogFile.txt', 'w') 
def print_log(msg): 
    print(msg) 
    logFile.write(msg) 

print_log('Hello World!') 

logFile.close() 

線條的東西,但是這仍然沒有捕捉到來自其他代碼和庫使用控制檯輸出。 有沒有辦法在執行結束時保存python腳本的控制檯輸出?我覺得應該有一個簡單的方法來做到這一點,但我所有的研究都沒有找到合適的解決方案。

+0

您需要用您自己的包裝器替換sys.stdout,該包裝器將所有寫入並傳遞到原始sys.stdout。 –

+0

@MaksymMarkov是的,我認爲這是真正的解決方案,這是我在我的問題中的代碼片斷得到的。雖然我希望像這樣的東西已經被編寫和成熟,或者已經是Python的內置函數。 – KDecker

回答

1

我用這一個在我的項目之一:

import io 
import sys 
from enum import Enum 


class Tee(io.StringIO): 
    class Source(Enum): 
     STDOUT = 1 
     STDERR = 2 

    def __init__(self, clone=Source.STDOUT, *args, **kwargs): 
     super().__init__(*args, **kwargs) 

     self._clone = clone 

     if clone == Tee.Source.STDOUT: 
      self._out = sys.stdout 
     elif clone == Tee.Source.STDERR: 
      self._out = sys.stderr 
     else: 
      raise ValueError("Clone has to be STDOUT or STDERR.") 

    def write(self, *args, **kwargs): 
     self._out.write(*args, **kwargs) 
     return super().write(*args, **kwargs) 

    def __enter__(self): 
     if self._clone == Tee.Source.STDOUT: 
      sys.stdout = self 
     else: 
      sys.stderr = self 
     self.seek(io.SEEK_END) 
     return self 

    def __exit__(self, exc_type, exc_val, exc_tb): 
     if self._clone == Tee.Source.STDOUT: 
      sys.stdout = self._out 
     else: 
      sys.stderr = self._out 
     self.seek(0) 
     return False 

基本上它究竟是幹什麼的馬克西姆馬爾科夫在一個差的評論稱。我通常不想拖延任何輸出,所以我寫了這個Tee,捕獲所有輸出到stdout(或stderr)的文本,立即打印並保存到緩衝區以備後用。當代碼退出with塊時,它也會關注「修復」sys.stdout

使用的例子:

if __name__ == "__main__": 
    with Tee() as tee: 
     print("Hello World!") 

    print(tee.read()) 

有喜歡無需額外的代碼你不能用塊內的使用tee.read()一些缺點。但在我的情況下,我總是需要處理整個塊的輸出。

相關問題