| 導航:起始頁 > Dive Into Python > 異常和文件處理 > 與文件對象共事 | << >> | ||||
深入 Python :Dive Into Python 中文版Python 從新手到專家 [Dip_5.4b_CPyUG_Release] |
|||||
Python 有一個內置函數,open,用來打開在磁盤上的文件。open 返回一個文件對象,它擁有一些方法和屬性,可以得到被打開文件的信息,以及對被打開文件進行操作。
>>> f = open("/music/_singles/kairo.mp3", "rb")>>> f
<open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.mode
'rb' >>> f.name
'/music/_singles/kairo.mp3'
| open 方法可以接收三個參數:文件名、模式和緩沖區參數。只有第一個參數 (文件名) 是必須的;其它兩個是可選的。如果沒有指定,文件以文本方式打開。這里我們以二進制方式打開文件進行讀取。(print open.__doc__ 會給出所有可能模式的很好的解釋。) | |
| open 函數返回一個對象 (到現在為止,這一點應該不會使你感到吃驚)。一個文件對象有幾個有用的屬性。 | |
| 文件對象的 mode 屬性告訴你文件以何種模式被打開。 | |
| 文件對象的 name 屬性告訴你文件對象所打開的文件名。 |
你打開文件之后,你要做的第一件事是從中讀取,正如下一個例子所展示的。
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.tell()0 >>> f.seek(-128, 2)
>>> f.tell()
7542909 >>> tagData = f.read(128)
>>> tagData 'TAGKAIRO****THE BEST GOA ***DJ MARY-JANE*** Rave Mix 2000http://mp3.com/DJMARYJANE \037' >>> f.tell()
7543037
打開文件消耗系統資源,并且其間其它程序可能無法訪問它們 (取決于文件模式)。這就是一旦操作完畢就該關閉文件的重要所在。
>>> f <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closedFalse >>> f.close()
>>> f <closed file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988> >>> f.closed
True >>> f.seek(0)
Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.tell() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.read() Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: I/O operation on closed file >>> f.close()
| 文件對象的 closed 屬性表示對象是打開還是關閉了文件。在本例中,文件仍然打開著 (closed 是 False)。 | |
| 為了關閉文件,調用文件對象的 close 方法。這樣就釋放掉你加在文件上的鎖 (如果有的話),刷新被緩沖的系統還未寫入的輸出 (如果有的話),并且釋放系統資源。 | |
| closed 屬性證實了文件被關閉了。 | |
| 文件被關閉了,但這并不意味著文件對象不再存在。變量 f 將繼續存在,直到它超出作用域或被手工刪除。然而,一旦文件被關閉,操作它的方法就沒有一個能使用;它們都會引發異常。 | |
| 對一個文件已經關閉的文件對象調用 close 不會 引發異常,它靜靜地失敗。 |
現在你已經足能理解前一章的例子程序 fileinfo.py 的文件處理代碼了。下面這個例子展示了如何安全地打開文件和讀取文件,以及優美地處理錯誤。
try:
fsock = open(filename, "rb", 0)
try:
fsock.seek(-128, 2)
tagdata = fsock.read(128)
finally:
fsock.close()
.
.
.
except IOError:
pass | 因為打開和讀取文件有風險,并且可能引發異常,所有這些代碼都用一個 try...except 塊封裝。(嘿,標準化的縮近不好嗎?這就是你開始欣賞它的地方。) | |
| open 函數可能引發 IOError 異常。(可能是文件不存在。) | |
| seek 方法可能引發 IOError 異常。(可能是文件長度小于 128 字節。) | |
| read 方法可能引發 IOError 異常。(可能磁盤有壞扇區,或它在一個網絡驅動器上,而網絡剛好斷了。) | |
| 這是新的:一個 try...finally 塊。一旦文件通過 open 函數被成功地打開,我們應該絕對保證把它關閉,即使是在 seek 或 read 方法引發了一個異常時。try...finally 塊可以用來:在 finally 塊中的代碼將總是 被執行,甚至某些東西在 try 塊中引發一個異常也會執行。可以這樣考慮,不管在路上發生什么,代碼都會被 “即將滅亡” 地執行。 | |
| 最后,處理我們的 IOError 異常。它可能是由調用 open、seek 或 read 引發的 IOError 異常。這里,我們其實不用關心,因為將要做的事就是靜靜地忽略它然后繼續。(記住,pass 是一條不做任何事的 Python 語句。) 這樣完全合法,“處理” 一個異常可以明確表示不做任何事。它仍然被認為處理過了,并且處理將正常繼續,從 try...except 塊的下一行代碼開始。 |
正如你所期待的,你也能用與讀取文件同樣的方式寫入文件。有兩種基本的文件模式:
如果文件還不存在,任意一種模式都將自動創建文件,因此從來不需要任何復雜的邏輯:“如果 log 文件還不存在,將創建一個新的空文件,正因為如此,你可以第一次就打開它”。打開文件并開始寫就可以了。
>>> logfile = open('test.log', 'w')>>> logfile.write('test succeeded')
>>> logfile.close() >>> print file('test.log').read()
test succeeded >>> logfile = open('test.log', 'a')
>>> logfile.write('line 2') >>> logfile.close() >>> print file('test.log').read()
test succeededline 2
<< 異常和文件處理 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
for 循環 >> |