python重新導向標準輸入、標準輸出和標準錯誤

來源:互聯網
上載者:User

UNIX使用者已經對標準輸入、標準輸出和標準錯誤的概念熟悉了。這一節是為其它不熟悉的人準備的。

標準輸出和標準錯誤(通常縮寫為 stdout 和 stderr)是建立在每個UNIX系統內的管道(pipe)。當你 print 某東西時,結果輸出到 stdout 管道中;當你的程式崩潰並列印出調試資訊時(象Python中的錯誤跟蹤),結果輸出到 stderr 管道中。通常這兩個管道只與你正在工作的終端視窗相聯,所以當一個程式列印輸出時,你可以看到輸出,並且當一個程式崩潰時,你可以看到調試資訊。(如果你在一個基於視窗的Python
IDE系統上工作,stdout 和 stderr 預設為“互動視窗”。)

例 5.32. stdout 和 stderr 介紹

>>> for i in range(3):...     print 'Dive in'             Dive inDive inDive in>>> import sys>>> for i in range(3):...     sys.stdout.write('Dive in') Dive inDive inDive in>>> for i in range(3):...     sys.stderr.write('Dive in') Dive inDive inDive in

正如我們在例 3.28中看到的,我們可以使用Python內建的 range 函數來建立簡單的計數迴圈,即重複某物一定的次數。

stdout 是一個類檔案對象;調用它的 write 函數會列印出任何給出的字串。事實上,這就是 print 函數真正所做的;它會在正列印的字串後面加上斷行符號分行符號,並調用sys.stdout.write。

在最簡單的例子中,stdout 和 stderr 將它們的輸出發送到同一個地方:Python IDE,或終端(如果你正從命令列運行Python)。象 stdout,stderr 並不為你增加斷行符號分行符號;如果需要,要自已加上。

stdout 和 stderr 都是類檔案對象,就象我們在提取輸入源中所討論的一樣,但它們都是唯寫的。它們沒有 read 方法,只有 write。然而,它們的確是類檔案對象,並且你可以將任意檔案對象或類檔案對象賦給它們來重新導向輸出。

例 5.33. 重新導向輸出

[f8dy@oliver kgp]$ python2 stdout.pyDive in[f8dy@oliver kgp]$ cat out.logThis message will be logged instead of displayed

如果你還沒有這樣做,你可以下載本書中用到的本例和其它例子。

#stdout.pyimport sysprint 'Dive in'                                          saveout = sys.stdout                                     fsock = open('out.log', 'w')                             sys.stdout = fsock                                       print 'This message will be logged instead of displayed' sys.stdout = saveout                                     fsock.close()                                            

這樣會列印到IDE的“互動視窗”中(或終端,如果你從命令列運行這一指令碼)。

始終在重新導向 stdout 之前儲存它,這樣你可以在後面將其設回正常。

開啟一個新檔案用於寫入。

將所有後續的輸出重新導向到我們剛開啟的新檔案上。

這樣只會將輸出結果“列印”到記錄檔中;在IDE視窗中或在螢幕上不會看到輸出結果。

在我們將 stdout 搞亂之前,讓我們把它設回原來的方式。

關閉記錄檔。

重新導向 stderr 完全以相同的方式進行,用 sys.stderr 代替 sys.stdout。

例 5.34. 重新導向錯誤資訊

[f8dy@oliver kgp]$ python2 stderr.py[f8dy@oliver kgp]$ cat error.logTraceback (most recent line last):  File "stderr.py", line 5, in ?    raise Exception, 'this error will be logged'Exception: this error will be logged

如果你還沒有這樣做,你可以下載本書中用到的本例和其它例子。

#stderr.pyimport sysfsock = open('error.log', 'w')               sys.stderr = fsock                           raise Exception, 'this error will be logged' 

開啟我們想用來儲存調試資訊的記錄檔。

將我們新開啟的記錄檔的檔案對象賦給 stderr 重新導向標準錯誤。

引發一個異常。從螢幕輸出上我們可以注意到這樣沒有在螢幕上列印出任何東西。所以正常跟蹤資訊已經寫進 error.log。

還要注意我們既沒有顯示地關閉記錄檔,也沒有將 stderr 設回它的初始值。這樣挺好,因為一旦程式崩潰(由於我們的異常),Python將替我們清理和關閉檔案,並且 stderr 永遠不恢複不會造成什麼不同。因為,我提到過,一旦程式崩潰,則Python也結束。如果你希望在同一個指令碼的後面去做其它的事情,恢複初始值對 stdout 更為重要。

另一方面,標準輸入是唯讀檔案對象,同時它表示從前面某個程式的資料流入這個程式。這一點可能對典型的Mac OS使用者可能沒什麼意義,或者甚至是對Windows使用者也是如此,除非你更習慣在MS-DOS命令列下工作。它的工作方式是:你可以在單個檔案中構造一個命令列的鏈,這樣一個程式的輸出成為鏈中下一個程式的輸入。第一個程式簡單地輸出到標準輸出(本身不需要任何特別的重定義,只是執行正常的 print 什麼的),同時下個程式從標準輸入讀入,作業系統會小心地將一個程式的輸出串連到下一個程式的輸入。

例 5.35. 連結命令

[f8dy@oliver kgp]$ python2 kgp.py -g binary.xml         01100111[f8dy@oliver kgp]$ cat binary.xml                       <?xml version="1.0"?><!DOCTYPE grammar PUBLIC "-//diveintopython.org//DTD Kant Generator Pro v1.0//EN" "kgp.dtd"><grammar><ref id="bit">  <p>0</p>  <p>1</p></ref><ref id="byte">  <p><xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/>\<xref id="bit"/><xref id="bit"/><xref id="bit"/><xref id="bit"/></p></ref></grammar>[f8dy@oliver kgp]$ cat binary.xml | python2 kgp.py -g - 10110001

正如我們在接觸中看到的,這樣會列印出8個隨機位元(0 或 1)的字串。

這樣會簡單地列印出 binary.xml 的全部內容。(Windows使用者應該使用 type 代替 cat。)

這樣會列印 binary.xml 的內容,但是“|”字元,叫做管道符,表示輸出內容不會列印到螢幕上。相反,它們成為下個命令(在本例中調用我們的Python指令碼)的標準輸入。

我們沒有指定一個模組(象 binary.xml),而是指定“-”,這會讓我們的指令碼從標準輸入而不是從磁碟上的一個特別檔案中裝入文法。(在下個例子中有更多關於它是如何發生的內容。)這樣效果同第一個文法(我們直接指定文法檔案名稱)是一樣的,但它考慮了這裡的擴充的可能性。不只是簡單地執行 cat binary.xml,我們可以運行一個可以動態產生文法的指令碼,然後可以將它通過管道輸入到我們的指令碼中。文法可以來自任何地方:資料庫,或某個文法產生元指令碼什麼的。要點就是我們完全不必修改我們的 kgp.py 指令碼就可以同任何這種功能進行合并。我們要做的只是能夠從標準輸入中接收文法檔案,並且我們可以將所有其它的邏輯分散到另一個程式中。

那麼當文法檔案是“-”時我們的指令碼是如何中從標準輸入讀入的呢?沒什麼神秘的,就是編碼。

例 5.36. 在 kgp.py 中從標準輸入讀入

def openAnything(source):    if source == "-":    import sys        return sys.stdin    # try to open with urllib (if source is http, ftp, or file URL)    import urllib    try:[... 略 ...]

這是來自 toolbox.py 中的 openAnything 函數,我們在提取輸入源中討論過的。我們所做的全部是在函數的開始處添加三行代碼,用來檢查是否 source 是“-”,如果是,我們返回sys.stdin。實際上,就是這樣!記住,stdin 是一個帶有 read 方法的類檔案對象,所以我們代碼的其餘部分(在 kgp.py 中,我們調用 openAnything 的地方)一點沒有改變。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.