<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            6.2. 與文件對象共事

            Python 有一個內置函數,open,用來打開在磁盤上的文件。open 返回一個文件對象,它擁有一些方法和屬性,可以得到被打開文件的信息,以及對被打開文件進行操作。

            例 6.3. 打開文件

            >>> f = open("/music/_singles/kairo.mp3", "rb") 1
            >>> f                                           2
            <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988>
            >>> f.mode                                      3
            'rb'
            >>> f.name                                      4
            '/music/_singles/kairo.mp3'
            1 open 方法可以接收三個參數:文件名、模式和緩沖區參數。只有第一個參數 (文件名) 是必須的;其它兩個是可選的。如果沒有指定,文件以文本方式打開。這里我們以二進制方式打開文件進行讀取。(print open.__doc__ 會給出所有可能模式的很好的解釋。)
            2 open 函數返回一個對象 (到現在為止,這一點應該不會使你感到吃驚)。一個文件對象有幾個有用的屬性。
            3 文件對象的 mode 屬性告訴你文件以何種模式被打開。
            4 文件對象的 name 屬性告訴你文件對象所打開的文件名。

            6.2.1. 讀取文件

            你打開文件之后,你要做的第一件事是從中讀取,正如下一個例子所展示的。

            例 6.4. 讀取文件

            >>> f
            <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988>
            >>> f.tell()              1
            0
            >>> f.seek(-128, 2)       2
            >>> f.tell()              3
            7542909
            >>> tagData = f.read(128) 4
            >>> tagData
            'TAGKAIRO****THE BEST GOA         ***DJ MARY-JANE***            
            Rave Mix                      2000http://mp3.com/DJMARYJANE     \037'
            >>> f.tell()              5
            7543037
            1 一個文件對象維護它所打開文件的狀態。文件對象的 tell 方法告訴你在被打開文件中的當前位置。因為我們還沒有對這個文件做任何事,當前位置為 0,它是文件的起始處。
            2 文件對象的 seek 方法在被打開文件中移動到另一個位置。第二個參數指出第一個參數是什么意思:0 表示移動到一個絕對位置 (從文件起始處算起),1 表示移到一個相對位置 (從當前位置算起),還有 2 表示相對于文件尾的位置。因為我們搜索的 MP3 標記保存在文件的末尾,我們使用 2 并且告訴文件對象從文件尾移動到 128 字節的位置。
            3 tell 方法確認了當前位置已經移動了。
            4 read 方法從被打開文件中讀取指定個數的字節,并且返回含有讀取數據的字符串。可選參數指定了讀取的最大字節數。如果沒有指定參數,read 將讀到文件末尾。(我們本可以在這里簡單地說 read() ,因為我們確切地知道在文件的何處,事實上,我們讀的是最后 128 個字節。) 讀出的數據賦給變量 tagData,并且當前的位置根據所讀的字節數作了修改。
            5 tell 方法確認了當前位置已經移動了。如果做一下算術,你會看到在讀了 128 個字節之后,位置數已經增加了 128。

            6.2.2. 關閉文件

            打開文件消耗系統資源,并且其間其它程序可能無法訪問它們 (取決于文件模式)。這就是一旦操作完畢就該關閉文件的重要所在。

            例 6.5. 關閉文件

            >>> f
            <open file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988>
            >>> f.closed       1
            False
            >>> f.close()      2
            >>> f
            <closed file '/music/_singles/kairo.mp3', mode 'rb' at 010E3988>
            >>> f.closed       3
            True
            >>> f.seek(0)      4
            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()      5
            1 文件對象的 closed 屬性表示對象是打開還是關閉了文件。在本例中,文件仍然打開著 (closedFalse)。
            2 為了關閉文件,調用文件對象的 close 方法。這樣就釋放掉你加在文件上的鎖 (如果有的話),刷新被緩沖的系統還未寫入的輸出 (如果有的話),并且釋放系統資源。
            3 closed 屬性證實了文件被關閉了。
            4 文件被關閉了,但這并不意味著文件對象不再存在。變量 f 將繼續存在,直到它超出作用域或被手工刪除。然而,一旦文件被關閉,操作它的方法就沒有一個能使用;它們都會引發異常。
            5 對一個文件已經關閉的文件對象調用 close 不會 引發異常,它靜靜地失敗。

            6.2.3. 處理 I/O 錯誤

            現在你已經足能理解前一章的例子程序 fileinfo.py 的文件處理代碼了。下面這個例子展示了如何安全地打開文件和讀取文件,以及優美地處理錯誤。

            例 6.6. MP3FileInfo 中的文件對象

                    try:                                1
                        fsock = open(filename, "rb", 0) 2
                        try:                           
                            fsock.seek(-128, 2)         3
                            tagdata = fsock.read(128)   4
                        finally:                        5
                            fsock.close()              
                        .
                        .
                        .
                    except IOError:                     6
                        pass                           
            1 因為打開和讀取文件有風險,并且可能引發異常,所有這些代碼都用一個 try...except 塊封裝。(嘿,標準化的縮近不好嗎?這就是你開始欣賞它的地方。)
            2 open 函數可能引發 IOError 異常。(可能是文件不存在。)
            3 seek 方法可能引發 IOError 異常。(可能是文件長度小于 128 字節。)
            4 read 方法可能引發 IOError 異常。(可能磁盤有壞扇區,或它在一個網絡驅動器上,而網絡剛好斷了。)
            5 這是新的:一個 try...finally 塊。一旦文件通過 open 函數被成功地打開,我們應該絕對保證把它關閉,即使是在 seekread 方法引發了一個異常時。try...finally 塊可以用來:在 finally 塊中的代碼將總是 被執行,甚至某些東西在 try 塊中引發一個異常也會執行。可以這樣考慮,不管在路上發生什么,代碼都會被 “即將滅亡” 地執行。
            6 最后,處理我們的 IOError 異常。它可能是由調用 openseekread 引發的 IOError 異常。這里,我們其實不用關心,因為將要做的事就是靜靜地忽略它然后繼續。(記住,pass 是一條不做任何事的 Python 語句。) 這樣完全合法,“處理” 一個異常可以明確表示不做任何事。它仍然被認為處理過了,并且處理將正常繼續,從 try...except 塊的下一行代碼開始。

            6.2.4. 寫入文件

            正如你所期待的,你也能用與讀取文件同樣的方式寫入文件。有兩種基本的文件模式:

            • 追加 (Append) 模式將數據追加到文件尾。
            • 寫入 (write) 模式將覆蓋文件的原有內容。

            如果文件還不存在,任意一種模式都將自動創建文件,因此從來不需要任何復雜的邏輯:“如果 log 文件還不存在,將創建一個新的空文件,正因為如此,你可以第一次就打開它”。打開文件并開始寫就可以了。

            例 6.7. 寫入文件

            >>> logfile = open('test.log', 'w') 1
            >>> logfile.write('test succeeded') 2
            >>> logfile.close()
            >>> print file('test.log').read()   3
            test succeeded
            >>> logfile = open('test.log', 'a') 4
            >>> logfile.write('line 2')
            >>> logfile.close()
            >>> print file('test.log').read()   5
            test succeededline 2
            
            1 你可以大膽地開始創建新文件 test.log 或覆蓋現有文件,并為寫入目的而打開它。(第二個參數 "w" 的意思是為文件寫入而打開。) 是的,它和想象中的一樣危險。我希望你不要關心文件以前的內容,因為它現在已經不存在了。
            2 你可以使用 open 返回的文件對象的 write 方法向一個新打開的文件添加數據。
            3 fileopen 的同義語。這一行語句打開文件,讀取內容,并打印它們。
            4 碰巧你知道 test.log 存在 (因為你剛向它寫完了數據),所以你可以打開它并向其追加數據。("a" 參數的意思是為追加目的打開文件。) 實際上即使文件不存在你也可以這樣做,因為以追加方式打開一文件時,如果需要的話會創建文件。但是追加操作從不 損壞文件的現有內容。
            5 正如你所看到的,原來的行和你以追加方式寫入的第二行現在都在 test.log 中了。同時注意兩行之間并沒包含回車符。因為兩次寫入文件時都沒有明確地寫入回車符,所以文件中沒有包含回車符。你可以用 "\n" 寫入回車符。因為你沒做這項工作,所以你寫到文件的所有內容都將顯示在同一行上。

            進一步閱讀

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线