io
--- 用於處理流的核心工具¶
原始碼: Lib/io.py
概述¶
io
模組提供了 Python 用於處理各種 I/O 型別的主要工具。I/O 主要有三種類型:文字 I/O、二進位制 I/O 和原始 I/O。這些都是通用類別,每種類別都可以使用各種後端儲存。屬於任一類別的具體物件都稱為檔案物件。其他常用術語有流和類檔案物件。
無論屬於哪種類別,每個具體的流物件都具有多種能力:它可以是隻讀、只寫或讀寫的。它還可以支援任意的隨機訪問(向前或向後搜尋到任意位置),或只支援順序訪問(例如套接字或管道)。
所有流都嚴格檢查你提供給它們的資料型別。例如,將一個 str
物件傳遞給二進位制流的 write()
方法將會引發 TypeError
。同樣,將一個 bytes
物件傳遞給文字流的 write()
方法也會引發該異常。
文字 I/O¶
文字 I/O 期望併產生 str
物件。這意味著,無論何時,當後端儲存原生為位元組(例如檔案)時,資料的編碼和解碼都會透明地進行,同時還會選擇性地轉換平臺特定的換行符。
建立文字流的最簡單方法是使用 open()
,並可選擇指定編碼:
f = open("myfile.txt", "r", encoding="utf-8")
記憶體中的文字流也可以作為 StringIO
物件使用:
f = io.StringIO("some initial text data")
備註
當使用非阻塞流時,請注意,如果流無法立即執行操作,對文字 I/O 物件的讀取操作可能會引發 BlockingIOError
。
文字流 API 在 TextIOBase
的文件中有詳細描述。
二進位制 I/O¶
二進位制 I/O(也稱為緩衝 I/O)期望接收類位元組物件併產生 bytes
物件。不執行任何編碼、解碼或換行符轉換。這類流可用於所有非文字資料,也可用於需要手動控制文字資料處理的情況。
建立二進位制流的最簡單方法是使用 open()
,並在模式字串中加入 'b'
:
f = open("myfile.jpg", "rb")
記憶體中的二進位制流也可以作為 BytesIO
物件使用:
f = io.BytesIO(b"some initial binary data: \x00\x01")
二進位制流 API 在 BufferedIOBase
的文件中有詳細描述。
其他庫模組可能提供了建立文字或二進位制流的額外方式。例如 socket.socket.makefile()
。
原始 I/O¶
原始 I/O(也稱為無緩衝 I/O)通常用作二進位制流和文字流的底層構建塊;使用者程式碼很少需要直接操作原始流。儘管如此,你還是可以透過在二進位制模式下開啟檔案並停用緩衝來建立一個原始流:
f = open("myfile.jpg", "rb", buffering=0)
原始流 API 在 RawIOBase
的文件中有詳細描述。
文字編碼¶
TextIOWrapper
和 open()
的預設編碼是與區域設定相關的(locale.getencoding()
)。
然而,許多開發者在開啟以 UTF-8 編碼的文字檔案(例如 JSON、TOML、Markdown 等)時會忘記指定編碼,因為大多數 Unix 平臺預設使用 UTF-8 區域設定。這會導致 bug,因為對於大多數 Windows 使用者來說,其區域設定編碼並非 UTF-8。例如:
# May not work on Windows when non-ASCII characters in the file.
with open("README.md") as f:
long_description = f.read()
因此,強烈建議在開啟文字檔案時明確指定編碼。如果你想使用 UTF-8,請傳遞 encoding="utf-8"
。若要使用當前區域設定的編碼,自 Python 3.10 起支援 encoding="locale"
。
參見
- Python UTF-8 模式
Python UTF-8 模式可用於將預設編碼從特定於區域設定的編碼更改為 UTF-8。
- PEP 686
Python 3.15 將預設啟用 Python UTF-8 模式。
可選的 EncodingWarning¶
在 3.10 版新加入: 更多詳情請參閱 PEP 597。
要找出哪裡使用了預設的區域設定編碼,你可以啟用 -X warn_default_encoding
命令列選項,或設定 PYTHONWARNDEFAULTENCODING
環境變數。當使用預設編碼時,這將發出一個 EncodingWarning
。
如果你提供的 API 使用 open()
或 TextIOWrapper
,並將 encoding=None
作為引數傳遞,你可以使用 text_encoding()
,這樣如果 API 的呼叫者沒有傳遞 encoding
,就會發出一個 EncodingWarning
。不過,對於新的 API,請考慮預設使用 UTF-8(即 encoding="utf-8"
)。
高層模組介面¶
- io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)¶
這是內建函式
open()
的別名。此函式會引發一個審計事件
open
,其引數為 path、mode 和 flags。mode 和 flags 引數可能已根據原始呼叫被修改或推斷得出。
- io.open_code(path)¶
以模式
'rb'
開啟所提供的檔案。當打算將檔案內容視為可執行程式碼時,應使用此函式。path 應該是一個
str
並且是絕對路徑。此函式的行為可能會被先前對
PyFile_SetOpenCodeHook()
的呼叫所覆蓋。然而,假設 path 是一個str
型別的絕對路徑,open_code(path)
的行為應始終與open(path, 'rb')
相同。覆蓋其行為的目的是為了對檔案進行額外的驗證或預處理。在 3.8 版本加入。
- io.text_encoding(encoding, stacklevel=2, /)¶
這是一個輔助函式,適用於使用
open()
或TextIOWrapper
並且帶有encoding=None
引數的可呼叫物件。如果 encoding 不為
None
,此函式返回 encoding。否則,它將根據UTF-8 模式返回"locale"
或"utf-8"
。如果
sys.flags.warn_default_encoding
為真且 encoding 為None
,此函式會發出一個EncodingWarning
。stacklevel 指定警告發出的位置。例如:def read_text(path, encoding=None): encoding = io.text_encoding(encoding) # stacklevel=2 with open(path, encoding) as f: return f.read()
在此示例中,會為
read_text()
的呼叫者發出一個EncodingWarning
。更多資訊請參閱文字編碼。
在 3.10 版本加入。
在 3.11 版更改: 當 UTF-8 模式啟用且 encoding 為
None
時,text_encoding()
返回 "utf-8"。
- exception io.BlockingIOError¶
這是內建異常
BlockingIOError
的相容性別名。
- exception io.UnsupportedOperation¶
一個繼承自
OSError
和ValueError
的異常,當在流上呼叫不支援的操作時引發。
參見
sys
包含標準 IO 流:
sys.stdin
、sys.stdout
和sys.stderr
。
類層次結構¶
I/O 流的實現被組織成一個類的層次結構。首先是抽象基類 (ABC),它們用於指定流的各種類別,然後是提供標準流實現的具體類。
備註
抽象基類還為某些方法提供了預設實現,以幫助實現具體的流類。例如,BufferedIOBase
提供了 readinto()
和 readline()
的未最佳化實現。
I/O 層次結構的頂層是抽象基類 IOBase
。它定義了流的基本介面。但是請注意,讀寫流之間沒有分離;如果實現不支援某個給定的操作,允許引發 UnsupportedOperation
。
RawIOBase
ABC 擴充套件了 IOBase
。它處理流中位元組的讀寫。FileIO
子類化了 RawIOBase
,為機器檔案系統中的檔案提供介面。
BufferedIOBase
ABC 擴充套件了 IOBase
。它處理原始二進位制流 (RawIOBase
) 上的緩衝。它的子類 BufferedWriter
、BufferedReader
和 BufferedRWPair
分別緩衝可寫、可讀以及可讀可寫的原始二進位制流。BufferedRandom
為可查詢的流提供了緩衝介面。另一個 BufferedIOBase
的子類 BytesIO
是一個記憶體中的位元組流。
TextIOBase
ABC 擴充套件了 IOBase
。它處理其位元組表示文字的流,並處理與字串之間的編碼和解碼。TextIOWrapper
繼承自 TextIOBase
,是緩衝原始流 (BufferedIOBase
) 的緩衝文字介面。最後,StringIO
是一個用於文字的記憶體流。
引數名稱不屬於規範的一部分,只有 open()
的引數才意在用作關鍵字引數。
下表總結了 io
模組提供的 ABC:
ABC (抽象基類) |
繼承自 |
存根方法 (Stub Methods) |
混入方法和屬性 (Mixin Methods and Properties) |
---|---|---|---|
|
|
||
|
繼承自 |
||
|
繼承自 |
||
|
繼承自 |
I/O 基類¶
- class io.IOBase¶
所有 I/O 類的抽象基類。
這個類為許多方法提供了空的抽象實現,派生類可以有選擇地覆蓋這些實現;預設實現代表了一個不可讀、不可寫或不可查詢的檔案。
儘管
IOBase
沒有宣告read()
或write()
,因為它們的簽名會變化,但實現和客戶端應將這些方法視為介面的一部分。此外,當呼叫不支援的操作時,實現可能會引發ValueError
(或UnsupportedOperation
)。從檔案中讀取或寫入檔案的二進位制資料的基本型別是
bytes
。其他類位元組物件也可用作方法引數。文字 I/O 類處理str
資料。請注意,對一個已關閉的流呼叫任何方法(甚至是查詢)都是未定義的。在這種情況下,實現可能會引發
ValueError
。IOBase
(及其子類)支援迭代器協議,這意味著可以對IOBase
物件進行迭代,以產生流中的行。行的定義略有不同,取決於流是二進位制流(產生位元組)還是文字流(產生字串)。請參閱下面的readline()
。IOBase
也是一個上下文管理器,因此支援with
語句。在此示例中,file 在with
語句塊完成後被關閉——即使發生異常也是如此:with open('spam.txt', 'w') as file: file.write('Spam and eggs!')
IOBase
提供了這些資料屬性和方法:- close()¶
重新整理並關閉此流。如果檔案已經關閉,此方法無效。一旦檔案關閉,對檔案的任何操作(例如讀或寫)都將引發
ValueError
。為方便起見,允許多次呼叫此方法;但只有第一次呼叫會生效。
- closed¶
如果流已關閉,則為
True
。
- flush()¶
如果適用,重新整理流的寫緩衝區。對於只讀和非阻塞流,此操作無效。
- isatty()¶
如果流是互動式的(即連線到終端/tty 裝置),則返回
True
。
- readline(size=-1, /)¶
從流中讀取並返回一行。如果指定了 size,則最多讀取 size 個位元組。
對於二進位制檔案,行終止符始終為
b'\n'
;對於文字檔案,可以使用open()
的 newline 引數來選擇可識別的行終止符。
- readlines(hint=-1, /)¶
從流中讀取並返回一個行的列表。可以指定 hint 來控制讀取的行數:如果到目前為止所有行的總大小(位元組/字元數)超過 hint,則不再讀取更多行。
hint 值為
0
或更小,以及None
,都被視為無提示。請注意,已經可以使用
for line in file: ...
來迭代檔案物件,而無需呼叫file.readlines()
。
- seek(offset, whence=os.SEEK_SET, /)¶
將流的位置更改為給定的位元組 offset,相對於 whence 指示的位置進行解釋,並返回新的絕對位置。whence 的值有:
os.SEEK_SET
或0
– 流的開始(預設);offset 應為零或正數os.SEEK_CUR
或1
– 當前流位置;offset 可以是負數os.SEEK_END
或2
– 流的末尾;offset 通常為負數
在 3.1 版新加入:
SEEK_*
常量。在 3.3 版新加入: 一些作業系統可能支援其他值,例如
os.SEEK_HOLE
或os.SEEK_DATA
。檔案的有效值可能取決於它是以文字模式還是二進位制模式開啟。
- seekable()¶
如果流支援隨機訪問,則返回
True
。如果為False
,seek()
、tell()
和truncate()
將引發OSError
。
- tell()¶
返回當前流的位置。
- truncate(size=None, /)¶
將流的大小調整為給定的 size 位元組(如果未指定 size,則為當前位置)。當前流的位置不變。此調整大小可以擴充套件或縮小當前檔案大小。在擴充套件的情況下,新檔案區域的內容取決於平臺(在大多數系統上,額外的位元組用零填充)。返回新的檔案大小。
在 3.5 版更改: 現在,Windows 在擴充套件檔案時會用零填充。
- writable()¶
如果流支援寫入,則返回
True
。如果為False
,write()
和truncate()
將引發OSError
。
- writelines(lines, /)¶
向流中寫入一個行的列表。不會新增行分隔符,因此通常提供的每一行末尾都應有行分隔符。
- class io.RawIOBase¶
原始二進位制流的基類。它繼承自
IOBase
。原始二進位制流通常提供對底層作業系統裝置或 API 的低階訪問,並且不嘗試將其封裝在高階原語中(此功能在緩衝二進位制流和文字流的更高級別完成,本頁稍後將描述)。
RawIOBase
除了IOBase
的方法外,還提供了這些方法:- read(size=-1, /)¶
從物件中讀取最多 size 個位元組並返回。為方便起見,如果 size 未指定或為 -1,則返回直到 EOF 的所有位元組。否則,只進行一次系統呼叫。如果作業系統呼叫返回的位元組數少於 size,則可能返回少於 size 的位元組。
如果返回 0 位元組,並且 size 不為 0,這表示檔案結束。如果物件處於非阻塞模式且沒有可用位元組,則返回
None
。預設實現委託給
readall()
和readinto()
。
- readall()¶
讀取並返回流中直到 EOF 的所有位元組,必要時對流進行多次呼叫。
- class io.BufferedIOBase¶
支援某種緩衝的二進位制流的基類。它繼承自
IOBase
。與
RawIOBase
的主要區別在於方法read()
、readinto()
和write()
將(分別)嘗試讀取請求的全部輸入或發出所有提供的資料。此外,如果底層原始流處於非阻塞模式,當系統返回會阻塞時,
write()
將引發BlockingIOError
並帶有BlockingIOError.characters_written
屬性,而read()
將返回已讀取的資料,或者如果沒有可用資料則返回None
。此外,
read()
方法沒有一個委託給readinto()
的預設實現。一個典型的
BufferedIOBase
實現不應該繼承自RawIOBase
實現,而是包裝一個,就像BufferedWriter
和BufferedReader
所做的那樣。BufferedIOBase
除了從IOBase
繼承的屬性和方法外,還提供或覆蓋了以下內容:- raw¶
BufferedIOBase
處理的底層原始流(一個RawIOBase
例項)。這不屬於BufferedIOBase
API 的一部分,並且在某些實現中可能不存在。
- detach()¶
將底層原始流從緩衝區中分離出來並返回它。
在原始流被分離後,緩衝區處於不可用狀態。
一些緩衝區,如
BytesIO
,沒有單一原始流的概念可從此方法返回。它們會引發UnsupportedOperation
。在 3.1 版本加入。
- read(size=-1, /)¶
讀取並返回最多 size 個位元組。如果引數省略、為
None
或為負數,則儘可能多地讀取。返回的位元組數可能少於請求的數量。如果流已經到達 EOF,則返回一個空的
bytes
物件。可能會進行多次讀取,並且在遇到特定錯誤時可能會重試呼叫,更多細節請參閱os.read()
和 PEP 475。返回的位元組數少於 size 並不意味著即將到達 EOF。當儘可能多地讀取時,如果可用,預設實現將使用
raw.readall
(它應該實現RawIOBase.readall()
),否則將迴圈讀取,直到 read 返回None
、一個空的bytes
或一個不可重試的錯誤。對於大多數流來說,這是到 EOF,但對於非阻塞流,可能會有更多資料可用。備註
當底層原始流是非阻塞時,實現可能會在沒有可用資料時引發
BlockingIOError
或返回None
。io
實現返回None
。
- read1(size=-1, /)¶
讀取並返回最多 size 個位元組,呼叫
readinto()
,根據 PEP 475 的規定,如果遇到EINTR
可能會重試。如果 size 是-1
或未提供,實現將為 size 選擇一個任意值。備註
當底層原始流是非阻塞時,實現可能會在沒有可用資料時引發
BlockingIOError
或返回None
。io
實現返回None
。
- readinto(b, /)¶
將位元組讀入一個預先分配的可寫的類位元組物件 b 中,並返回讀取的位元組數。例如,b 可能是一個
bytearray
。與
read()
類似,可能會對底層原始流發出多次讀取,除非後者是互動式的。如果底層原始流處於非阻塞模式,並且當前沒有可用資料,則會引發
BlockingIOError
。
- readinto1(b, /)¶
將位元組讀入預先分配的可寫的類位元組物件 b 中,最多隻呼叫一次底層原始流的
read()
(或readinto()
)方法。返回讀取的位元組數。如果底層原始流處於非阻塞模式,並且當前沒有可用資料,則會引發
BlockingIOError
。在 3.5 版本加入。
- write(b, /)¶
寫入給定的類位元組物件 b,並返回寫入的位元組數(總是等於 b 的位元組長度,因為如果寫入失敗將引發
OSError
)。根據實際實現,這些位元組可能會立即寫入底層流,或者為了效能和延遲原因而儲存在緩衝區中。在非阻塞模式下,如果需要寫入的資料無法被原始流在不阻塞的情況下全部接受,則會引發
BlockingIOError
。呼叫者在此方法返回後可以釋放或修改 b,因此實現應僅在方法呼叫期間訪問 b。
原始檔案 I/O¶
- class io.FileIO(name, mode='r', closefd=True, opener=None)¶
一個原始二進位制流,表示一個包含位元組資料的作業系統級檔案。它繼承自
RawIOBase
。name 可以是以下兩種之一:
一個表示將要開啟的檔案路徑的字串或
bytes
物件。在這種情況下,closefd 必須為True
(預設值),否則將引發錯誤。一個整數,表示現有作業系統級檔案描述符的編號,生成的
FileIO
物件將給予對此的訪問許可權。當 FileIO 物件關閉時,此檔案描述符也將被關閉,除非 closefd 設定為False
。
mode 可以是
'r'
,'w'
,'x'
或'a'
,分別用於讀取(預設)、寫入、獨佔建立或追加。當以寫入或追加模式開啟時,如果檔案不存在則會建立檔案;以寫入模式開啟時,檔案將被截斷。當以建立模式開啟時,如果檔案已存在,將引發FileExistsError
。以建立模式開啟檔案意味著寫入,因此此模式的行為類似於'w'
。在模式中新增'+'
以允許同時讀寫。此類上的
read()
(當用正數引數呼叫時)、readinto()
和write()
方法只會進行一次系統呼叫。可以透過傳遞一個可呼叫物件作為 opener 來使用自定義開啟器。然後透過呼叫 opener 並傳入 (name, flags) 來獲取檔案物件的底層檔案描述符。opener 必須返回一個開啟的檔案描述符(將
os.open
作為 opener 傳遞的結果類似於傳遞None
)。新建立的檔案是不可繼承的。
有關使用 opener 引數的示例,請參見內建函式
open()
。在 3.3 版更改: 增加了 opener 引數。增加了
'x'
模式。在 3.4 版更改: 檔案現在是不可繼承的。
FileIO
除了RawIOBase
和IOBase
的屬性外,還提供了這些資料屬性:- mode¶
建構函式中給定的模式。
- name¶
檔名。如果在建構函式中沒有給出名稱,則這是檔案的檔案描述符。
緩衝流¶
緩衝 I/O 流提供了比原始 I/O 更高級別的 I/O 裝置介面。
- class io.BytesIO(initial_bytes=b'')¶
一個使用記憶體中位元組緩衝區的二進位制流。它繼承自
BufferedIOBase
。當呼叫close()
方法時,緩衝區將被丟棄。可選引數 initial_bytes 是一個包含初始資料的類位元組物件。
BytesIO
除了從BufferedIOBase
和IOBase
繼承的方法外,還提供或覆蓋了這些方法:- getbuffer()¶
返回一個對緩衝區內容的可讀寫檢視,而無需複製它們。此外,修改檢視將透明地更新緩衝區的內容:
>>> b = io.BytesIO(b"abcdef") >>> view = b.getbuffer() >>> view[2:4] = b"56" >>> b.getvalue() b'ab56ef'
備註
只要該檢視存在,
BytesIO
物件就不能被調整大小或關閉。在 3.2 版本加入。
- readinto1(b, /)¶
在
BytesIO
中,這與readinto()
相同。在 3.5 版本加入。
- class io.BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE)¶
一個緩衝二進位制流,為可讀、不可查詢的
RawIOBase
原始二進位制流提供更高級別的訪問。它繼承自BufferedIOBase
。當從此物件讀取資料時,可能會從底層原始流請求更大量的資料,並儲存在內部緩衝區中。然後,緩衝的資料可以在後續讀取中直接返回。
建構函式為給定的可讀 raw 流和 buffer_size 建立一個
BufferedReader
。如果省略 buffer_size,則使用DEFAULT_BUFFER_SIZE
。BufferedReader
除了從BufferedIOBase
和IOBase
繼承的方法外,還提供或覆蓋了這些方法:- peek(size=0, /)¶
從流中返回位元組,但不移動檔案指標。返回的位元組數可能比請求的要少或多。如果底層的原始流是非阻塞的,並且操作會阻塞,則返回空位元組。
- read(size=-1, /)¶
在
BufferedReader
中,這與io.BufferedIOBase.read()
相同。
- read1(size=-1, /)¶
在
BufferedReader
中,這與io.BufferedIOBase.read1()
相同。在 3.7 版更改: size 引數現在是可選的。
- class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)¶
一個帶緩衝的二進位制流,為可寫的、不可查詢的
RawIOBase
原始二進位制流提供了更高級別的訪問。它繼承自BufferedIOBase
。當向此物件寫入時,資料通常會放入一個內部緩衝區。在各種情況下,緩衝區將被寫出到底層的
RawIOBase
物件中,包括:當緩衝區對於所有待處理的資料來說太小時;
當呼叫
flush()
時;當請求
seek()
時(對於BufferedRandom
物件);當
BufferedWriter
物件被關閉或銷燬時。
建構函式為給定的可寫 raw 流建立一個
BufferedWriter
。如果未指定 buffer_size,則預設為DEFAULT_BUFFER_SIZE
。BufferedWriter
在BufferedIOBase
和IOBase
的方法之外,還提供或重寫了以下方法:- flush()¶
強制將緩衝區中保留的位元組寫入原始流。如果原始流阻塞,則應引發
BlockingIOError
。
- write(b, /)¶
寫入 類位元組物件 b,並返回寫入的位元組數。在非阻塞模式下,如果緩衝區需要寫出但原始流阻塞,則會引發
BlockingIOError
,並設定其BlockingIOError.characters_written
屬性。
- class io.BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)¶
一個帶緩衝的二進位制流,為可查詢的
RawIOBase
原始二進位制流提供了更高級別的訪問。它繼承自BufferedReader
和BufferedWriter
。建構函式為第一個引數中給定的可查詢原始流建立一個讀取器和寫入器。如果省略了 buffer_size,則預設為
DEFAULT_BUFFER_SIZE
。BufferedRandom
能夠完成BufferedReader
或BufferedWriter
所能做的一切。此外,保證實現了seek()
和tell()
。
- class io.BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, /)¶
一個帶緩衝的二進位制流,為兩個不可查詢的
RawIOBase
原始二進位制流(一個可讀,另一個可寫)提供了更高級別的訪問。它繼承自BufferedIOBase
。reader 和 writer 是分別是可讀和可寫的
RawIOBase
物件。如果省略了 buffer_size,則預設為DEFAULT_BUFFER_SIZE
。BufferedRWPair
實現了BufferedIOBase
的所有方法,除了detach()
會引發UnsupportedOperation
。警告
BufferedRWPair
不會嘗試同步對其底層原始流的訪問。你不應該將同一個物件同時作為讀取器和寫入器傳遞給它;應改用BufferedRandom
。
文字 I/O¶
- class io.TextIOBase¶
文字流的基類。此類為流 I/O 提供了基於字元和行的介面。它繼承自
IOBase
。TextIOBase
在IOBase
的基礎上提供或重寫了以下資料屬性和方法:- encoding¶
用於將流的位元組解碼為字串,以及將字串編碼為位元組的編碼名稱。
- errors¶
解碼器或編碼器的錯誤設定。
- newlines¶
一個字串、一個字串元組或
None
,表示迄今為止已轉換的換行符。根據實現和初始建構函式標誌,此屬性可能不可用。
- buffer¶
TextIOBase
處理的底層二進位制緩衝區(一個BufferedIOBase
或RawIOBase
例項)。這不是TextIOBase
API 的一部分,並且在某些實現中可能不存在。
- detach()¶
將底層二進位制緩衝區與
TextIOBase
分離並返回它。底層緩衝區被分離後,
TextIOBase
處於不可用狀態。一些
TextIOBase
的實現,如StringIO
,可能沒有底層緩衝區的概念,呼叫此方法將引發UnsupportedOperation
。在 3.1 版本加入。
- seek(offset, whence=SEEK_SET, /)¶
將流位置更改為給定的 offset。行為取決於 whence 引數。whence 的預設值為
SEEK_SET
。SEEK_SET
或0
:從流的開頭開始查詢(預設值);offset 必須是由TextIOBase.tell()
返回的數字,或者為零。任何其他的 offset 值都會產生未定義的行為。SEEK_CUR
或1
:“查詢”到當前位置;offset 必須為零,這是一個無操作(所有其他值都不支援)。SEEK_END
或2
:查詢到流的末尾;offset 必須為零(所有其他值都不支援)。
以一個不透明的數字形式返回新的絕對位置。
在 3.1 版新加入:
SEEK_*
常量。
- tell()¶
以一個不透明的數字形式返回當前流的位置。該數字通常不表示底層二進位制儲存中的位元組數。
- write(s, /)¶
將字串 s 寫入流中,並返回寫入的字元數。
- class io.TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False)¶
一個帶緩衝的文字流,為
BufferedIOBase
緩衝二進位制流提供了更高級別的訪問。它繼承自TextIOBase
。encoding 給出了流將被解碼或編碼的編碼名稱。在 UTF-8 模式下,預設為 UTF-8。否則,預設為
locale.getencoding()
。可以使用encoding="locale"
來顯式指定當前區域的編碼。更多資訊請參見 文字編碼。errors 是一個可選字串,用於指定如何處理編碼和解碼錯誤。傳遞
'strict'
以在出現編碼錯誤時引發ValueError
異常(預設的None
具有相同的效果),或傳遞'ignore'
來忽略錯誤。(注意,忽略編碼錯誤可能導致資料丟失。)'replace'
會在格式錯誤的資料處插入一個替換標記(如'?'
)。'backslashreplace'
會將格式錯誤的資料替換為反斜槓轉義序列。在寫入時,可以使用'xmlcharrefreplace'
(替換為適當的 XML 字元引用)或'namereplace'
(替換為\N{...}
轉義序列)。任何已透過codecs.register_error()
註冊的其他錯誤處理名稱也是有效的。newline 控制如何處理行尾。它可以是
None
、''
、'\n'
、'\r'
和'\r\n'
。它的工作方式如下:從流中讀取輸入時,如果 newline 是
None
,則啟用通用換行模式。輸入中的行可以以'\n'
、'\r'
或'\r\n'
結尾,這些都會在返回給呼叫者之前被翻譯成'\n'
。如果 newline 是''
,則啟用通用換行模式,但行尾會未經翻譯地返回給呼叫者。如果 newline 是任何其他合法值,輸入行僅由給定的字串終止,並且行尾會未經翻譯地返回給呼叫者。向流中寫入輸出時,如果 newline 是
None
,則任何寫入的'\n'
字元都將被翻譯成系統預設的行分隔符os.linesep
。如果 newline 是''
或'\n'
,則不進行翻譯。如果 newline 是任何其他合法值,則任何寫入的'\n'
字元都將被翻譯成給定的字串。
如果 line_buffering 為
True
,則當對 write 的呼叫包含換行符或回車符時,會隱式呼叫flush()
。如果 write_through 為
True
,則對write()
的呼叫保證不會被緩衝:任何寫入TextIOWrapper
物件的資料都會立即傳遞給其底層的二進位制 buffer。在 3.3 版更改: 增加了 write_through 引數。
在 3.3 版更改: 預設的 encoding 現在是
locale.getpreferredencoding(False)
而不是locale.getpreferredencoding()
。不要使用locale.setlocale()
臨時更改區域編碼,應使用當前區域編碼而不是使用者首選的編碼。在 3.10 版更改: encoding 引數現在支援
"locale"
這個偽編碼名稱。備註
當底層原始流是非阻塞時,如果讀取操作無法立即完成,可能會引發
BlockingIOError
。TextIOWrapper
在TextIOBase
和IOBase
的基礎上提供了以下資料屬性和方法:- line_buffering¶
行緩衝是否啟用。
- write_through¶
寫入操作是否立即傳遞給底層二進位制緩衝區。
在 3.7 版本加入。
- reconfigure(*, encoding=None, errors=None, newline=None, line_buffering=None, write_through=None)¶
使用新的 encoding、errors、newline、line_buffering 和 write_through 設定重新配置此文字流。
未指定的引數將保持當前設定,但如果指定了 encoding 而未指定 errors,則使用
errors='strict'
。如果已經從流中讀取了資料,則無法更改編碼或換行符。另一方面,在寫入後更改編碼是可能的。
此方法在設定新引數之前會隱式地重新整理流。
在 3.7 版本加入。
在 3.11 版更改: 該方法支援
encoding="locale"
選項。
- class io.StringIO(initial_value='', newline='\n')¶
使用記憶體中文字緩衝區的文字流。它繼承自
TextIOBase
。當呼叫
close()
方法時,文字緩衝區將被丟棄。可以透過提供 initial_value 來設定緩衝區的初始值。如果啟用了換行符轉換,換行符將像透過
write()
一樣進行編碼。流的位置被設定在緩衝區的開頭,這模擬了以w+
模式開啟現有檔案,使其準備好從頭開始立即寫入或覆蓋初始值。要模擬以a+
模式開啟檔案準備追加,請使用f.seek(0, io.SEEK_END)
將流重新定位到緩衝區的末尾。newline 引數的工作方式與
TextIOWrapper
類似,但在向流中寫入輸出時,如果 newline 為None
,則在所有平臺上換行符都寫為\n
。StringIO
在TextIOBase
和IOBase
的基礎上提供了以下方法:用法示例:
import io output = io.StringIO() output.write('First line.\n') print('Second line.', file=output) # Retrieve file contents -- this will be # 'First line.\nSecond line.\n' contents = output.getvalue() # Close object and discard memory buffer -- # .getvalue() will now raise an exception. output.close()
- class io.IncrementalNewlineDecoder¶
一個輔助編解碼器,用於在通用換行模式下解碼換行符。它繼承自
codecs.IncrementalDecoder
。
靜態型別¶
以下協議可用於為簡單的流讀取或寫入操作的函式和方法引數添加註解。它們都使用了 @typing.runtime_checkable
裝飾器。
- class io.Reader[T]¶
用於從檔案或其他輸入流讀取的通用協議。
T
通常是str
或bytes
,但也可以是從流中讀取的任何型別。在 3.14 版本加入。
- read()¶
- read(size, /)
從輸入流中讀取資料並返回。如果指定了 size,它應該是一個整數,並且最多會讀取 size 個專案(位元組/字元)。
例如:
def read_it(reader: Reader[str]): data = reader.read(11) assert isinstance(data, str)
- class io.Writer[T]¶
用於向檔案或其他輸出流寫入的通用協議。
T
通常是str
或bytes
,但也可以是任何可以寫入流中的型別。在 3.14 版本加入。
- write(data, /)¶
將 data 寫入輸出流,並返回寫入的專案數(位元組/字元)。
例如:
def write_binary(writer: Writer[bytes]): writer.write(b"Hello world!\n")
有關可用於靜態型別檢查的其他 I/O 相關協議和類,請參閱 用於處理 I/O 的 ABC 和協議。
效能¶
本節討論了提供的具體 I/O 實現的效能。
二進位制 I/O¶
透過即使在使用者請求單個位元組時也只讀寫大塊資料,緩衝 I/O 隱藏了呼叫和執行作業系統無緩衝 I/O 例程的任何低效。其增益取決於作業系統和執行的 I/O 型別。例如,在一些現代作業系統(如 Linux)上,無緩衝磁碟 I/O 可以與緩衝 I/O 一樣快。然而,最重要的是,無論平臺和後備裝置如何,緩衝 I/O 都能提供可預測的效能。因此,對於二進位制資料,幾乎總是優先使用緩衝 I/O 而不是無緩衝 I/O。
文字 I/O¶
在二進位制儲存(如檔案)上的文字 I/O 比在相同儲存上的二進位制 I/O 慢得多,因為它需要使用字元編解碼器在 Unicode 和二進位制資料之間進行轉換。這在處理大量文字資料(如大型日誌檔案)時會變得很明顯。此外,由於使用了重構演算法,tell()
和 seek()
都相當慢。
多執行緒¶
FileIO
物件是執行緒安全的,前提是它們所包裝的作業系統呼叫(例如在 Unix 下的 read(2))也是執行緒安全的。
二進位制緩衝物件(BufferedReader
、BufferedWriter
、BufferedRandom
和 BufferedRWPair
的例項)使用鎖來保護其內部結構;因此,可以安全地從多個執行緒同時呼叫它們。
TextIOWrapper
物件不是執行緒安全的。
可重入性¶
二進位制緩衝物件(BufferedReader
、BufferedWriter
、BufferedRandom
和 BufferedRWPair
的例項)是不可重入的。雖然在正常情況下不會發生可重入呼叫,但在 signal
處理程式中進行 I/O 操作時可能會出現。如果一個執行緒試圖重新進入它已經在訪問的緩衝物件,會引發 RuntimeError
。注意,這並不禁止另一個執行緒進入該緩衝物件。
以上內容也隱式地擴充套件到文字檔案,因為 open()
函式會將一個緩衝物件包裝在 TextIOWrapper
內部。這包括標準流,因此也影響了內建的 print()
函式。