函數?open()?返回文件對象,通常的用法需要兩個參數:open(filename,?mode)。
~~~
>>> f = open('/tmp/workfile', 'w')
~~~
第一個參數是一個標識文件名的字符串。第二個參數是由有限的字母組成的字符串,描述了文件將會被如何使用。可選的?_模式_?有:?'r',此選項使文件只讀;?'w'?,此選項使文件只寫(對于同名文件,該操作使原有文件被覆蓋);?'a'?,此選項以追加方式打開文件;?'r+'?,此選項以讀寫方式打開文件; 模式 參數是可選的。如果沒有指定,默認為?'r'?模式。
在 Windows 平臺上,?'b'?模式以二進制方式打開文件,所以可能會有類似于?'rb'?,?'wb'?,'r+b'?等等模式組合。Windows 平臺上文本文件與二進制文件是有區別的,讀寫文本文件時,行尾會自動添加行結束符。這種后臺操作方式對 ASCII 文本文件沒有什么問題,但是操作?JPEG?或?EXE這樣的二進制文件時就會產生破壞。在操作這些文件時一定要記得以二進制模式打開。在 Unix 上,加一個?'b'?模式也一樣是無害的,所以你可以一切二進制文件處理中平臺無關的使用它。
### 7.2.1\. 文件對象方法
本節中的示例都默認文件對象?f?已經創建。
要讀取文件內容,需要調用?f.read(size),該方法讀取若干數量的數據并以字符串形式返回其內容,_size_?是可選的數值,指定字符串長度。如果沒有指定?_size_?或者指定為負數,就會讀取并返回整個文件。當文件大小為當前機器內存兩倍時,就會產生問題。反之,會盡可能按比較大的?_size_?讀取和返回數據。如果到了文件末尾,f.read()?會返回一個空字符串(”“):
~~~
>>> f.read()
'This is the entire file.\n'
>>> f.read()
''
~~~
f.readline()?從文件中讀取單獨一行,字符串結尾會自動加上一個換行符(?\n?),只有當文件最后一行沒有以換行符結尾時,這一操作才會被忽略。這樣返回值就不會有混淆,如果?f.readline()返回一個空字符串,那就表示到達了文件末尾,如果是一個空行,就會描述為?'\n',一個只包含換行符的字符串:
~~~
>>> f.readline()
'This is the first line of the file.\n'
>>> f.readline()
'Second line of the file\n'
>>> f.readline()
''
~~~
f.readlines()?返回一個列表,其中包含了文件中所有的數據行。如果給定了?_sizehint_?參數,就會讀入多于一行的比特數,從中返回多行文本。這個功能通常用于高效讀取大型行文件,避免了將整個文件讀入內存。這種操作只返回完整的行。
~~~
>>> f.readlines()
['This is the first line of the file.\n', 'Second line of the file\n']
~~~
一種替代的方法是通過遍歷文件對象來讀取文件行。這是一種內存高效、快速,并且代碼簡介的方式:
~~~
>>> for line in f:
... print(line, end='')
...
This is the first line of the file.
Second line of the file
~~~
雖然這種替代方法更簡單,但并不具備細節控制能力。因為這兩種方法處理行緩存的方式不同,千萬不能搞混。
f.write(string)?方法將 string 的內容寫入文件,并返回寫入字符的長度:
~~~
>>> f.write('This is a test\n')
15
~~~
想要寫入其他非字符串內容,首先要將它轉換為字符串:
~~~
>>> value = ('the answer', 42)
>>> s = str(value)
>>> f.write(s)
18
~~~
f.tell()?返回一個整數,代表文件對象在文件中的指針位置,該數值計量了自文件開頭到指針處的比特數。需要改變文件對象指針話話,使用?f.seek(offset,from_what)。指針在該操作中從指定的引用位置移動?_offset_?比特,引用位置由?_from_what_?參數指定。?_from_what_?值為 0 表示自文件起始處開始,1 表示自當前文件指針位置開始,2 表示自文件末尾開始。_from_what_?可以忽略,其默認值為零,此時從文件頭開始:
~~~
>>> f = open('/tmp/workfile', 'rb+')
>>> f.write(b'0123456789abcdef')
16
>>> f.seek(5) # Go to the 6th byte in the file
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2) # Go to the 3rd byte before the end
13
>>> f.read(1)
b'd'
~~~
在文本文件中(那些沒有使用?b?模式選項打開的文件),只允許從文件頭開始計算相對位置(使用?seek(0,?2)?從文件尾計算時就會引發異常)。
當你使用完一個文件時,調用?f.close()?方法就可以關閉它并釋放其占用的所有系統資源。 在調用f.close()?方法后,試圖再次使用文件對象將會自動失敗。
~~~
>>> f.close()
>>> f.read()
Traceback (most recent call last):
File "", line 1, in ?
ValueError: I/O operation on closed file
~~~
用關鍵字?with?處理文件對象是個好習慣。它的先進之處在于文件用完后會自動關閉,就算發生異常也沒關系。它是?try-finally?塊的簡寫:
~~~
>>> with open('/tmp/workfile', 'r') as f:
... read_data = f.read()
>>> f.closed
True
~~~
文件對象還有一些不太常用的附加方法,比如?isatty()?和?truncate()?在庫參考手冊中有文件對象的完整指南。
### 7.2.2.?pickle?模塊
我們可以很容易的讀寫文件中的字符串。數值就要多費點兒周折,因為?read()?方法只會返回字符串,應該將其傳入?int()?這樣的方法中,就可以將?'123'?這樣的字符轉為對應的數值 123。不過,當你需要保存更為復雜的數據類型,例如列表、字典,類的實例,事情就會變得更復雜了。
好在用戶不必要非得自己編寫和調試保存復雜數據類型的代碼。 Python 提供了一個名為?pickle?的標準模塊。這是一個令人贊嘆的模塊,幾乎可以把任何 Python 對象(甚至是一些 Python 代碼段!)表達為為字符串,這一過程稱之為封裝 (?_pickling_?)。從字符串表達出重新構造對象稱之為拆封(?_unpickling_?)。封裝狀態中的對象可以存儲在文件或對象中,也可以通過網絡在遠程的機器之間傳輸。
如果你有一個對象?x,一個以寫模式打開的文件對象?f,封裝對象的最簡單的方法只需要一行代碼:
`pickle.dump(x, f)`
如果?f?是一個以讀模式打開的文件對象,就可以重裝拆封這個對象:
`x = pickle.load(f)`
(如果不想把封裝的數據寫入文件,這里還有一些其它的變化可用。完整的?pickle?文檔請見 Python 庫參考手冊)。
pickle?是存儲 Python 對象以供其它程序或其本身以后調用的標準方法。提供這一組技術的是一個持久化對象(?_persistent_?對象)。因為?pickle?的用途很廣泛,很多 Python 擴展的作者都非常注意類似矩陣這樣的新數據類型是否適合封裝和拆封。
- Python 入門指南
- 1. 開胃菜
- 2. 使用 Python 解釋器
- 2.1. 調用 Python 解釋器
- 2.2. 解釋器及其環境
- 3. Python 簡介
- 3.1. 將 Python 當做計算器
- 3.2. 編程的第一步
- 4. 深入 Python 流程控制
- 4.1. if 語句
- 4.2. for 語句
- 4.3. range() 函數
- 4.4. break 和 continue 語句, 以及循環中的 else 子句
- 4.5. pass 語句
- 4.6. 定義函數
- 4.7. 深入 Python 函數定義
- 4.8. 插曲:編碼風格
- 5. 數據結構
- 5.1. 關于列表更多的內容
- 5.2. del 語句
- 5.3. 元組和序列
- 5.4. 集合
- 5.5. 字典
- 5.6. 循環技巧
- 5.7. 深入條件控制
- 5.8. 比較序列和其它類型
- 6. 模塊
- 6.1. 深入模塊
- 6.2. 標準模塊
- 6.3. dir() 函數
- 6.4. 包
- 7. 輸入和輸出
- 7.1. 格式化輸出
- 7.2. 文件讀寫
- 8. 錯誤和異常
- 8.1. 語法錯誤
- 8.2. 異常
- 8.3. 異常處理
- 8.4. 拋出異常
- 8.5. 用戶自定義異常
- 8.6. 定義清理行為
- 8.7. 預定義清理行為
- 9. 類
- 9.1. 術語相關
- 9.2. Python 作用域和命名空間
- 9.3. 初識類
- 9.4. 一些說明
- 9.5. 繼承
- 9.6. 私有變量
- 9.7. 補充
- 9.8. 異常也是類
- 9.9. 迭代器
- 9.10. 生成器
- 9.11. 生成器表達式
- 10. Python 標準庫概覽
- 10.1. 操作系統接口
- 10.2. 文件通配符
- 10.3. 命令行參數
- 10.4. 錯誤輸出重定向和程序終止
- 10.5. 字符串正則匹配
- 10.6. 數學
- 10.7. 互聯網訪問
- 10.8. 日期和時間
- 10.9. 數據壓縮
- 10.10. 性能度量
- 10.11. 質量控制
- 10.12. “瑞士軍刀”
- 11. 標準庫瀏覽 – Part II
- 11.1. 輸出格式
- 11.2. 模板
- 11.3. 使用二進制數據記錄布局
- 11.4. 多線程
- 11.5. 日志
- 11.6. 弱引用
- 11.7. 列表工具
- 11.8. 十進制浮點數算法
- 12. 接下來?
- 13. 交互式輸入行編輯歷史回溯
- 13.1. 行編輯
- 13.2. 歷史回溯
- 13.3. 快捷鍵綁定
- 13.4. 其它交互式解釋器
- 14. 浮點數算法:爭議和限制
- 14.1. 表達錯誤
- 15. 附錄
- 15.1. 交互模式