Python 的 `io` 模組
本文將說明 Python 的 io 模組。
我們將透過實際範例來解釋 Python 的 io 模組。
YouTube Video
Python 的 io 模組
輸入/輸出處理是各種資料操作(如檔案、網路、標準 I/O)的基礎。Python 的 io 模組提供了一組抽象類別,統一了這些輸入/輸出操作。理解這個模組的關鍵概念是「串流」(stream)的想法。
什麼是流?
串流是一種可以順序且持續地讀寫資料的抽象資料流。
當逐位元組讀取檔案內容,或是在網路上收發資料時,這些操作都可以用資料串流來處理。
透過抽象這個機制,不同來源的 I/O(如檔案、記憶體、網路)都可以用共同的讀寫操作來處理。
Python 的 io 模組提供了統一的串流介面,讓文字資料和二進位資料都能高效處理。
io 模組的基本結構
io 模組依據串流性質設計為三層架構。
-
底層原始層(
RawIOBase)RawIOBase處理最低階的位元組 I/O,例如作業系統的檔案描述符與裝置。 -
緩衝層(
BufferedIOBase)BufferedIOBase提供快取(緩衝區)以提升 I/O 效率。BufferedReader和BufferedWriter是典型的實例。 -
文字層(
TextIOBase)TextIOBase將位元組序列轉為字串並處理編碼。通常使用open()打開檔案時,會使用該層的TextIOWrapper。
多虧這樣的結構,io 模組能明確區分文字與二進位 I/O,並允許彈性組合。
io 模組的基本結構
最底層的 RawIOBase 負責作業系統的檔案描述符,其上層 BufferedIOBase 提供緩衝機制,頂層的 TextIOBase 則負責字串轉換。
1import io
2
3# Check the core base classes hierarchy
4print(io.IOBase.__subclasses__())- 這段程式碼是用來檢查繼承自
IOBase的抽象類別群。你可以看到TextIOBase、BufferedIOBase和RawIOBase,確認其階層架構。
io.IOBase:所有串流的基底類別
IOBase 是所有 I/O 物件的抽象基底類別,定義了如 close()、flush()、seekable() 等共通方法。它很少被直接使用,多半是經由衍生類別操作。
1import io
2
3f = io.StringIO("data")
4print(f.seekable()) # True
5print(f.readable()) # True
6print(f.writable()) # True
7f.close()- 這個範例說明了
IOBase的共通方法也可以在上層類別中使用。seekable()和readable()能幫助你檢查串流的屬性。
io.RawIOBase:最低層
RawIOBase 是最接近 OS 檔案描述符的層級,不會進行任何緩衝處理。典型的實作是 FileIO,以位元組為單位來讀寫。
1import io, os
2
3# Create a low-level FileIO object (no buffering)
4fd = os.open('raw_demo.bin', os.O_RDWR | os.O_CREAT)
5raw = io.FileIO(fd, mode='w+')
6raw.write(b'abc123')
7raw.seek(0)
8print(raw.read(6)) # b'abc123'
9raw.close()FileIO是RawIOBase的具體實現;所有讀寫都以bytes進行。若與上一層的BufferedIOBase結合,則能提升效率。
io.BufferedIOBase:中介層(具緩衝功能)
BufferedIOBase 是中間層,進行緩衝,以提升磁碟存取效能。主要實作類別有 BufferedReader、BufferedWriter、BufferedRandom 和 BufferedRWPair。
1import io
2
3# Create a buffered binary stream on top of a BytesIO (simulate file)
4base = io.BytesIO()
5buffered = io.BufferedWriter(base)
6buffered.write(b'Python IO buffering')
7buffered.flush()
8base.seek(0)
9print(base.read()) # b'Python IO buffering'- 此例中,透過
BufferedWriter寫入的資料會暫存於記憶體緩衝區,直到呼叫flush()才會真正傳送到下層。
BufferedReader 的範例
BufferedReader 是只讀的緩衝流,支援使用 peek() 和 read() 進行高效讀取。
1import io
2
3stream = io.BytesIO(b"1234567890")
4reader = io.BufferedReader(stream)
5print(reader.peek(5)) # b'12345' (non-destructive)
6print(reader.read(4)) # b'1234'
7print(reader.read(3)) # b'567'peek()僅檢視(偷看)資料,並不移動指標。搭配read()使用,可彈性控制緩衝機制。
io.TextIOBase:僅限文字的層級
TextIOBase 是處理字串的抽象層,內部會執行解碼和編碼操作。典型的實作類別為 TextIOWrapper。
1import io
2
3# Wrap a binary stream to handle text encoding
4binary = io.BytesIO()
5text_stream = io.TextIOWrapper(binary, encoding='utf-8')
6text_stream.write("\u3053\u3093\u306B\u3061\u306F")
7text_stream.flush()
8
9# Reset stream position
10binary.seek(0)
11
12# Read bytes once
13data = binary.read()
14
15# Show both raw bytes and decoded text
16print("Raw bytes:", data)
17print("Decoded text:", data.decode('utf-8'))- 在此範例中,
TextIOWrapper會將字串編碼成 UTF-8,並寫入底層的二進位串流。
以 TextIOWrapper 讀取的範例
讀取時會自動進行解碼。
1import io
2
3binary_data = io.BytesIO("Python I/O".encode('utf-8'))
4text_reader = io.TextIOWrapper(binary_data, encoding='utf-8')
5print(text_reader.read()) # 'Python I/O'TextIOWrapper是文字輸出入的基礎類別,幾乎所有高階檔案操作都以此為基礎。
io.StringIO:記憶體文字串流
StringIO 是允許你在記憶體中像操作檔案一樣操作字串的類別。它對 I/O 測試與暫時資料產生特別有用。
1import io
2
3text_buf = io.StringIO()
4text_buf.write("In-memory text stream")
5text_buf.seek(0)
6print(text_buf.read()) # 'In-memory text stream'StringIO無需使用磁碟即可進行類似檔案的操作,廣泛應用於單元測試。
io.BytesIO:記憶體二進位串流
BytesIO 是為了處理位元組序列(bytes)而設計的記憶體檔案類別。對於像是二進位處理或資料壓縮等不希望使用檔案的情境特別有用。
1import io
2
3buf = io.BytesIO()
4buf.write(b'\x01\x02\x03')
5buf.seek(0)
6print(list(buf.read())) # [1, 2, 3]BytesIO與BufferedIOBase有相同的介面,可作為許多檔案 API 的替代。
自訂串流(自行實作類別)
io 模組內的類別具有可擴充性,讓你可以自訂串流類別。下方範例展示了一個將所有寫入文字轉為大寫的 TextIOBase 子類別。
1import io
2
3class UpperTextIO(io.TextIOBase):
4 def __init__(self):
5 self.buffer = ""
6 def write(self, s):
7 self.buffer += s.upper()
8 return len(s)
9
10u = UpperTextIO()
11u.write("hello io")
12print(u.buffer) # "HELLO IO"- 只要遵守
TextIOBase的契約,你可以自訂任何此類行為。另外,也能輕鬆擴充串流類別至特定用途,如檔案或網路。
總結
io 模組將輸入/輸出處理按抽象與具體類別做分層整理。
RawIOBase是用於作業系統層級位元組 I/O 的類別。BufferedIOBase則提供高效快取層。TextIOBase負責管理字串的讀寫作業。StringIO與BytesIO則提供記憶體串流功能的類別。
了解這些類別能幫助你精確掌握 Python I/O 系統的運作,並將之應用於檔案操作、網路通訊以及測試串流的設計。
您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。