在Python里打開一個文件很簡單:
a_file = open('examples/chinese.txt', encoding='utf-8')Python有一個內置函數 open(),但需要注意:
Windows使用反斜杠來表示子目錄,但是Mac OS X和linux使用斜杠。但是,在Python中,斜杠永遠都是正確的,即使是在Windows環境下。filename,”參數是一個字符串。所有現代的操作系統(甚至Windows!)使用Unicode編碼方式來存儲文件名和目錄名。Python 3全面支持非ASCII編碼的路徑。文件不一定需要在本地磁盤上。也許你掛載了一個網絡驅動器。它也可以是一個完全虛擬的文件系統(an entirely virtual filesystem)上的文件。只要你的操作系統認為它是一個文件,并且能夠以文件的方式訪問,那么,Python就能打開它。 下面>>> a_file = open('examples/chinese.txt', encoding='utf-8')>>> a_file.mode ③'r'如果在打開文件的時候沒有指定訪問模式,Python默認設置模式為’r’,意思是“在文本模式下以只讀的方式打開?!痹谶@章的后面你會看到,文件的訪問模式有各種用途;不同模式能夠使你寫入一個文件,追加到一個文件,或者以二進制模式打開一個文件(在這種情況下,你處理的是字節,不再是字符)。
seek()方法使定位到文件中的特定字節。 read()方法可以使用一個可選的參數,即所要讀取的字符個數。 seek()和tell()方法總是以字節的方式計數,但是,由于你是以文本文件的方式打開的,read()方法以字符的個數計數。
>>> a_file.read() ①''>>> a_file.seek(0) ②0>>> a_file.read(16) ③'Dive Into Python'>>> a_file.read(1) ④' '>>> a_file.read(1)'是'>>> a_file.tell() ⑤20>>> a_file.seek(17) ①17>>> a_file.read(1) ②'是'>>> a_file.tell() ③20>>> a_file.seek(18) ①18>>> a_file.read(1) ②Traceback (most recent call last): File "<pyshell#12>", line 1, in <module> a_file.read(1) File "C:/Python31/lib/codecs.py", line 300, in decode (result, consumed) = self._buffer_decode(data, self.errors, final)UnicodeDecodeError: 'utf8' codec can't decode byte 0x98 in position 0: unexpected code byte#定位到第18th個字節,然后試圖讀取一個字符。但失敗了,因為在第18個字節處不存在字符。當已經完成了對文件的操作后就立即關閉它們,這很重要。
>>> a_file.close()然而,這還不夠(anticlimactic)。流對象a_file仍然存在;調用close()方法并沒有把對象本身銷毀。所以這并不是非常有效。
>>> a_file.close() >>> a_file.closed True已經關閉了的流對象確實還有一個有用的屬性:closed用來確認文件是否已經被關閉了。
try..finally也行。但是with更好
流對象有一個顯式的close()方法,但是如果代碼有缺陷,在調用close()方法以前就崩潰了呢 。所以使用with()。
with open('examples/chinese.txt', encoding='utf-8') as a_file: a_file.seek(17) a_character = a_file.read(1) PRint(a_character)這段代碼調用了open()函數,但是它卻一直沒有調用a_file.close()。with語句引出一個代碼塊,就像if語句或者for循環一樣。在這個代碼塊里,你可以使用變量a_file作為open()函數返回的流對象的引用。所以流對象的常規方法都是可用的 — seek(),read(),無論你想要調用什么。當with塊結束時,Python自動調用a_file.close()。
從技術上說,with語句創建了一個運行時環境(runtime context)。 with語句不只是針對文件而言的;它是一個用來創建運行時環境的通用框架(generic framework),告訴對象它們正在進入和離開一個運行時環境。 如果該對象是流對象,那么它就會做一些類似文件對象一樣有用的動作(就像自動關閉文件?。5悄莻€行為是被流對象自身定義的,而不是在with語句中。還有許多跟文件無關的使用上下文管理器(context manager)的方法。在這章的后面可以看到,你甚至可以自己創建它們。
Python 3.0支持字符串格式化,但是只支持顯式編號了的格式說明符。Python 3.1允許你在格式說明符里省略參數索引號。作為比照,下面是一個Python 3.0兼容的版本。
兩種方式:
1.“寫”模式會重寫文件。傳遞mode=’w’參數給open()函數。 2.“追加”模式會在文件末尾添加數據。傳遞mode=’a’參數給open()函數。
如果文件不存在,兩種模式下都會自動創建新文件。最后,在完成寫入后你應該馬上關閉文件,釋放文件句柄(file handle),并且保證數據被完整地寫入到了磁盤。 結合with會讓編程更簡單。
>>> with open('test.log', mode='w', encoding='utf-8') as a_file: ①... a_file.write('test succeeded') ②>>> with open('test.log', encoding='utf-8') as a_file:... print(a_file.read()) test succeeded>>> with open('test.log', mode='a', encoding='utf-8') as a_file: ③... a_file.write('and again')>>> with open('test.log', encoding='utf-8') as a_file:... print(a_file.read()) test succeededand again ④你是否注意到當你在打開文件用于寫入數據的時候傳遞給open()函數的encoding參數。它“非常重要”,不要忽略了!實際上你不能直接把字符寫入到文件;字符只是一種抽象。為了寫入字符到文件,Python需要知道如何將字符串轉換為字節序列。唯一能保證正確地執行轉換的方法就是當你為寫入而打開一個文件的時候,指定encoding參數。
用二進制模式打開文件很簡單,但是很精細。與文本模式唯一不同的是mode參數包含一個字符’b’。 字符 不等于 字節!!!
使用read()方法即可從虛擬文件讀取數據。 這聽起來跟你從打開一個真實文件得到的流對象一樣。不同之處在于你不再受限于真實的文件。能夠“讀取”的輸入源可以是任何東西:網頁,內存中的字符串,甚至是另外一個程序的輸出。只要你的函數使用的是流對象,調用對象的read()方法,你可以處理任何行為與文件類似的輸入源,而不需要為每種類型的輸入指定特別的代碼。
>>> a_string = 'PapayaWhip is the new black.'>>> import io ①>>> a_file = io.StringIO(a_string) ②>>> a_file.read() ③'PapayaWhip is the new black.'io模塊定義了StringIO類,你可以使用它來把內存中的字符串當作文件來處理。為了從字符串創建一個流對象,可以把想要作為“文件”使用的字符串傳遞給io.StringIO()來創建一個StringIO的實例。調用read()方法“讀取”整個“文件”,以StringIO對象為例即返回原字符串。 io.StringIO讓你能夠將一個字符串作為文本文件來看待。另外還有一個io.ByteIO類,它允許你將字節數組當做二進制文件來處理。gzip和bzip2是非Windows操作系統下最流行的兩種壓縮方式。
gzip模塊允許你創建用來讀寫gzip壓縮文件的流對象。該流對象支持read()方法(如果你以讀取模式打開)或者write()方法(如果你以寫入模式打開)。這就意味著,你可以使用從普通文件那兒學到的技術來直接讀寫gzip壓縮文件。 它也支持with語句,所以當你完成了對gzip壓縮文件的操作,Python可以為你自動關閉它。
sys.stdin, sys.stdout, sys.stderr,它們分別是標準輸入,標準輸出和標準錯誤。
>>> import sys>>> for i in range(3):... sys.stdout.write('is the') ②is theis theis the>>> for i in range(3):... sys.stderr.write('new black') ③new blacknew blacknew black>>> sys.stdout.read()Traceback (most recent call last): File "<stdin>", line 1, in <module>IOError: not readablesys.stdout和sys.stderr都是流對象,但是他們都只支持寫入。試圖調用他們的read()方法會引發IOError異常。
新聞熱點
疑難解答