| 導航:起始頁 > Dive Into Python > 腳本和流 > 標準輸入、輸出和錯誤 | << >> | ||||
深入 Python :Dive Into Python 中文版Python 從新手到專家 [Dip_5.4b_CPyUG_Release] |
|||||
UNIX 用戶已經對標準輸入、標準輸出和標準錯誤的概念非常熟悉了。這一節是為其他不熟悉的人準備的。
標準輸入和標準錯誤 (通常縮寫為 stdout 和 stderr) 是內建在每一個 UNIX 系統中的管道。當你 print 某些東西時,結果前往 stdout 管道;當你的程序崩潰并打印出調試信息 (例如 Python 中的 traceback (錯誤跟蹤)) 的時候,信息前往 stderr 管道。通常這兩個管道只與你正在工作的終端窗口相聯,所以當一個程序打印時,你可以看到輸出,而當一個程序崩潰時,你可以看到調試信息。(如果你正在一個基于窗口的 Python IDE 上工作,stdout 和 stderr 缺省為你的“交互窗口”。)
>>> for i in range(3): ... print 'Dive in'Dive in Dive in Dive 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
| 正如在例 6.9 “簡單計數”中看到的,你可以使用 Python 內置的 range 函數來構造簡單的計數循環,即重復某物一定的次數。 | |
| stdout 是一個類文件對象;調用它的 write 函數可以打印出你給定的任何字符串。實際上,這就是 print 函數真正做的事情;它在你打印的字符串后面加上一個硬回車,然后調用 sys.stdout.write 函數。 | |
| 在最簡單的例子中,stdout 和 stderr 把它們的輸出發送到相同的地方:Python IDE (如果你在一個 IDE 中的話),或者終端 (如果你從命令行運行 Python 的話)。和 stdout 一樣,stderr 并不為你添加硬回車;如果需要,要自己加上。 |
stdout 和 stderr 都是類文件對象,就像在第 10.1 節 “抽象輸入源”中討論的一樣,但是它們都是只寫的。它們都沒有 read 方法,只有 write 方法。然而,它們仍然是類文件對象,因此你可以將其它任何 (類) 文件對象賦值給它們來重定向其輸出。
[you@localhost kgp]$ python stdout.py Dive in [you@localhost kgp]$ cat out.log This message will be logged instead of displayed
(在 Windows 上,你要使用 type 來代替 cat 顯示文件的內容。)
如果您還沒有下載本書附帶的樣例程序, 可以 下載本程序和其他樣例程序。
#stdout.py import sys print '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()
![]()
重定向 stderr 以完全相同的方式進行,只要把 sys.stdout 改為 sys.stderr。
[you@localhost kgp]$ python stderr.py [you@localhost kgp]$ cat error.log Traceback (most recent line last): File "stderr.py", line 5, in ? raise Exception, 'this error will be logged' Exception: this error will be logged
如果您還沒有下載本書附帶的樣例程序, 可以 下載本程序和其他樣例程序。
#stderr.py import sys fsock = open('error.log', 'w')sys.stderr = fsock
raise Exception, 'this error will be logged'
![]()
![]()
向標準錯誤寫入錯誤信息是很常見的,所以有一種較快的語法可以立刻導出信息。
>>> print 'entering function' entering function >>> import sys >>> print >> sys.stderr, 'entering function'entering function
另一方面,標準輸入是一個只讀文件對象,它表示從前一個程序到這個程序的數據流。這個對于老的 Mac OS 用戶和 Windows 用戶可能不太容易理解,除非你受到過 MS-DOS 命令行的影響。在 MS-DOS 命令行中,你可以使用一行指令構造一個命令的鏈,使得一個程序的輸出就可以成為下一個程序的輸入。第一個程序只是簡單地輸出到標準輸出上 (程序本身沒有做任何特別的重定向,只是執行了普通的 print 語句等),然后,下一個程序從標準輸入中讀取,操作系統就把一個程序的輸出連接到一個程序的輸入。
[you@localhost kgp]$ python kgp.py -g binary.xml01100111 [you@localhost 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> [you@localhost kgp]$ cat binary.xml | python kgp.py -g -
![]()
10110001
| 正如你在第 9.1 節 “概覽”中看到的,該命令將只打印一個隨機的八位字符串,其中只有 0 或者 1。 | |
| 該處只是簡單地打印出整個 binary.xml 文檔的內容。(Windows 用戶應該用 type 代替 cat。) | |
| 該處打印 binary.xml 的內容,但是“|”字符,稱為“管道”符,說明內容不會打印到屏幕上;它們會成為下一個命令的標準輸入,在這個例子中是你調用的 Python 腳本。 | |
| 為了不用指定一個文件 (例如 binary.xml),你需要指定“-”,它會使得你的腳本從標準輸入載入腳本,而不是從磁盤上的特定文件。 (下一個例子更多地說明了這是如何實現的)。所以效果和第一種語法是一樣的,在那里你要直接指定語法文件,但是想想這里的擴展性。讓我們把 cat binary.xml 換成別的什么東西――例如運行一個腳本動態生成語法――然后通過管道將它導入你的腳本。它可以來源于任何地方:數據庫,或者是生成語法的元腳本,或者其他。你根本不需要修改你的 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: [... snip ...]
| 這是 toolbox.py 中的 openAnything 函數,以前在第 10.1 節 “抽象輸入源”中你已經檢視過了。所有你要做的就是在函數的開始加入 3 行代碼來檢測源是否是“-”;如果是,返回 sys.stdin。就這么簡單!記住,stdin 是一個擁有 read 方法的類文件對象,所以其它的代碼 (在 kgp.py 中,在那里你調用了 openAnything) 一點都不需要改動。 |
<< 腳本和流 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
查詢緩沖節點 >> |