Python學習之IO程式設計

stonezhu發表於2018-06-22

Python學習目錄

  1. 在Mac下使用Python3
  2. Python學習之資料型別
  3. Python學習之函式
  4. Python學習之高階特性
  5. Python學習之函數語言程式設計
  6. Python學習之模組
  7. Python學習之物件導向程式設計
  8. Python學習之物件導向高階程式設計
  9. Python學習之錯誤除錯和測試
  10. Python學習之IO程式設計
  11. Python學習之程式和執行緒
  12. Python學習之正則
  13. Python學習之常用模組
  14. Python學習之網路程式設計

IO在計算機中指Input/Output,也就是輸入和輸出。由於程式和執行時資料是在記憶體中駐留,由CPU這個超快的計算核心來執行,涉及到資料交換的地方,通常是磁碟、網路等,就需要IO介面。

IO程式設計

檔案讀寫

上程式碼:

try:
    //讀檔案
    f = open('/path/to/file', 'r')
    print(f.read())
    //寫檔案
    f = open('/Users/michael/test.txt', 'w')
    f.write('Hello, world!')
finally:
    if f:
        //關閉檔案
        f.close()
複製程式碼

等價於:

//讀檔案
with open('/path/to/file', 'r') as f:
    print(f.read())
//寫檔案
with open('/Users/michael/test.txt', 'w') as f:
    f.write('Hello, world!')
複製程式碼

開啟檔案

開啟文字檔案

1、讀模式開啟檔案

要以讀檔案的模式開啟一個檔案物件,使用Python內建的open()函式,傳入檔名和標示符:

>>> f = open('/Users/michael/test.txt', 'r')
複製程式碼

標示符'r'表示讀,這樣,我們就成功地開啟了一個檔案。

2、寫模式開啟檔案

>>> f = open('/Users/michael/test.txt', 'w')
複製程式碼

3、帶編碼方式開啟檔案(讀或者寫)

預設讀寫檔案的編碼方式是UTF-8,要讀取非UTF-8編碼的文字檔案,需要給open()函式傳入encoding引數,例如,讀取GBK編碼的檔案:

>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')
複製程式碼

開啟二進位制檔案

要讀取二進位制檔案,比如圖片、視訊等等,用'rb'模式開啟檔案即可:

>>> f = open('/Users/michael/test.jpg', 'rb')
複製程式碼

讀檔案

如果檔案開啟成功,接下來,呼叫read()方法可以一次讀取檔案的全部內容,Python把內容讀到記憶體,用一個str物件表示:

>>> f.read()
複製程式碼

呼叫read()會一次性讀取檔案的全部內容,如果檔案有10G,記憶體就爆了,所以,要保險起見,可以反覆呼叫read(size)方法,每次最多讀取size個位元組的內容。另外,呼叫readline()可以每次讀取一行內容,呼叫readlines()一次讀取所有內容並按行返回list。因此,要根據需要決定怎麼呼叫。

如果檔案很小,read()一次性讀取最方便;如果不能確定檔案大小,反覆呼叫read(size)比較保險;如果是配置檔案,呼叫readlines()最方便:

for line in f.readlines():
    print(line.strip()) # 把末尾的'\n'刪掉
複製程式碼

file-like Object

open()函式返回的這種有個read()方法的物件,在Python中統稱為file-like Object。除了file外,還可以是記憶體的位元組流,網路流,自定義流等等。file-like Object不要求從特定類繼承,只要寫個read()方法就行。

StringIO就是在記憶體中建立的file-like Object,常用作臨時緩衝。

寫檔案

寫檔案和讀檔案是一樣的,唯一區別是呼叫open()函式時,傳入識別符號'w'或者'wb'表示寫文字檔案或寫二進位制檔案:

f.write('Hello, world!')
複製程式碼

關閉檔案

最後一步是呼叫close()方法關閉檔案。檔案使用完畢後必須關閉,因為檔案物件會佔用作業系統的資源,並且作業系統同一時間能開啟的檔案數量也是有限的:

>>> f.close()
複製程式碼

StringIO和BytesIO

很多時候,資料讀寫不一定是檔案,也可以在記憶體中讀寫。

StringIO

StringIO顧名思義就是在記憶體中讀寫str。

要把str寫入StringIO,我們需要先建立一個StringIO,然後,像檔案一樣寫入即可:

>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())
hello world!
複製程式碼

getvalue()方法用於獲得寫入後的str。

要讀取StringIO,可以用一個str初始化StringIO,然後,像讀檔案一樣讀取:

>>> from io import StringIO
>>> f = StringIO('Hello!\nHi!\nGoodbye!')
>>> while True:
...     s = f.readline()
...     if s == '':
...         break
...     print(s.strip())
...
Hello!
Hi!
Goodbye!
複製程式碼

BytesIO

StringIO操作的只能是str,如果要操作二進位制資料,就需要使用BytesIO。

BytesIO實現了在記憶體中讀寫bytes,我們建立一個BytesIO,然後寫入一些bytes:

>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))
6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'
複製程式碼

請注意,寫入的不是str,而是經過UTF-8編碼的bytes。

和StringIO類似,可以用一個bytes初始化BytesIO,然後,像讀檔案一樣讀取:

>>> from io import BytesIO
>>> f = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
>>> f.read()
b'\xe4\xb8\xad\xe6\x96\x87'
複製程式碼

操作檔案和目錄

如果我們要操作檔案、目錄,可以在命令列下面輸入作業系統提供的各種命令來完成。比如dircp等命令。

如果要在Python程式中執行這些目錄和檔案的操作怎麼辦?其實作業系統提供的命令只是簡單地呼叫了作業系統提供的介面函式,Python內建的os模組也可以直接呼叫作業系統提供的介面函式。

操作檔案和目錄的函式一部分放在os模組中,一部分放在os.path模組中。

看看如何利用Python的特性來過濾檔案。比如我們要列出當前目錄下的所有目錄,只需要一行程式碼:

>>> [x for x in os.listdir('.') if os.path.isdir(x)]
['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Applications', 'Desktop', ...]
複製程式碼

要列出所有的.py檔案,也只需一行程式碼:

>>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']
複製程式碼

序列化

pickle

我們把變數從記憶體中變成可儲存或傳輸的過程稱之為序列化,在Python中叫pickling,在其他語言中也被稱之為serialization,marshalling,flattening等等,都是一個意思。

序列化之後,就可以把序列化後的內容寫入磁碟,或者通過網路傳輸到別的機器上。

反過來,把變數內容從序列化的物件重新讀到記憶體裡稱之為反序列化,即unpickling。

Python提供了pickle模組來實現序列化。Pickle的問題和所有其他程式語言特有的序列化問題一樣,就是它只能用於Python,並且可能不同版本的Python彼此都不相容,因此,只能用Pickle儲存那些不重要的資料,不能成功地反序列化也沒關係。

JSON

如果我們要在不同的程式語言之間傳遞物件,就必須把物件序列化為標準格式,比如XML,但更好的方法是序列化為JSON,因為JSON表示出來就是一個字串,可以被所有語言讀取,也可以方便地儲存到磁碟或者通過網路傳輸。JSON不僅是標準格式,並且比XML更快,而且可以直接在Web頁面中讀取,非常方便。

Python內建的json模組提供了非常完善的Python物件到JSON格式的轉換。我們先看看如何把Python物件變成一個JSON:

>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'
複製程式碼

dumps()方法返回一個str,內容就是標準的JSON。類似的,dump()方法可以直接把JSON寫入一個file-like Object

要把JSON反序列化為Python物件,用loads()或者對應的load()方法,前者把JSON的字串反序列化,後者從file-like Object中讀取字串並反序列化:

>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}
複製程式碼

由於JSON標準規定JSON編碼是UTF-8,所以我們總是能正確地在Python的str與JSON的字串之間轉換。

下一篇:Python學習之程式和執行緒

相關文章