io — 用於處理流的核心工具

原始碼: Lib/io.py


概述

io 模組提供了 Python 用於處理各種 I/O 型別的主要工具。主要有三種 I/O 型別:文字 I/O二進位制 I/O原始 I/O。這些是通用類別,每種類別都可以使用各種後備儲存。屬於這些類別中任何一個的具體物件都稱為檔案物件。其他常用術語是類檔案物件

每個具體的流物件,無論其類別如何,也都將具有各種功能:它可以是隻讀的、只寫的或讀寫的。它還可以允許任意隨機訪問(向前或向後查詢任何位置),或者僅允許順序訪問(例如,在套接字或管道的情況下)。

所有流都對其接收的資料型別非常注意。例如,將str物件傳遞給二進位制流的 write() 方法將引發 TypeError。同樣,將bytes物件傳遞給文字流的 write() 方法也會引發此錯誤。

在 3.3 版本中更改: 以前會引發 IOError 的操作現在會引發 OSError,因為 IOError 現在是 OSError 的別名。

文字 I/O

文字 I/O 預期並生成 str 物件。這意味著,當後備儲存本身由位元組組成時(例如在檔案的情況下),資料的編碼和解碼會透明地進行,並且可以選擇性地轉換特定於平臺的新行字元。

建立文字流的最簡單方法是使用 open(),可以選擇指定編碼

f = open("myfile.txt", "r", encoding="utf-8")

記憶體中文字流也可以作為 StringIO 物件使用

f = io.StringIO("some initial text data")

文字流 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 的文件中有詳細描述。

文字編碼

TextIOWrapperopen() 的預設編碼是特定於區域設定的 (locale.getencoding())。

但是,許多開發人員在開啟以 UTF-8 編碼的文字檔案(例如 JSON、TOML、Markdown 等)時忘記指定編碼,因為大多數 Unix 平臺預設使用 UTF-8 區域設定。這會導致錯誤,因為大多數 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

如果您提供一個使用 open()TextIOWrapper 並傳遞 encoding=None 作為引數的 API,則可以使用 text_encoding(),以便如果 API 的呼叫者未傳遞 encoding,將發出 EncodingWarning。但是,請考慮為新 API 預設使用 UTF-8(即 encoding="utf-8")。

高階模組介面

io.DEFAULT_BUFFER_SIZE

一個整數,包含模組的緩衝 I/O 類使用的預設緩衝區大小。open() 如果可能,將使用檔案的 blksize(透過 os.stat() 獲取)。

io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

這是內建 open() 函式的別名。

此函式會引發一個 審計事件 open,其引數為 pathmodeflagsmodeflags 引數可能已被修改或從原始呼叫中推斷出來。

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 為 true 且 encodingNone,則此函式會發出 EncodingWarningstacklevel 指定發出警告的位置。例如

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 模式且 encodingNone 時,text_encoding() 返回 "utf-8"。

exception io.BlockingIOError

這是內建 BlockingIOError 異常的相容性別名。

exception io.UnsupportedOperation

當在流上呼叫不支援的操作時引發的繼承自 OSErrorValueError 的異常。

另請參閱

sys

包含標準 IO 流:sys.stdinsys.stdoutsys.stderr

類層次結構

I/O 流的實現組織為類層次結構。 首先是 抽象基類 (ABCs),用於指定各種類別的流,然後是提供標準流實現的具體類。

注意

抽象基類還提供一些方法的預設實現,以幫助實現具體的流類。例如,BufferedIOBase 提供了 readinto()readline() 的未最佳化實現。

在 I/O 層次結構的頂部是抽象基類 IOBase。 它定義了流的基本介面。但是,請注意,流的讀取和寫入之間沒有分離;如果實現不支援給定的操作,則允許引發 UnsupportedOperation

RawIOBase ABC 擴充套件了 IOBase。 它處理將位元組讀取和寫入到流。 FileIO 子類化 RawIOBase,以提供對機器檔案系統中檔案的介面。

BufferedIOBase ABC 擴充套件了 IOBase。 它處理原始二進位制流 ( RawIOBase) 上的緩衝。它的子類 BufferedWriterBufferedReaderBufferedRWPair 分別緩衝可寫、可讀以及既可讀又可寫的原始二進位制流。BufferedRandom 提供了可搜尋流的緩衝介面。 另一個 BufferedIOBase 子類 BytesIO 是記憶體中位元組的流。

TextIOBase ABC 擴充套件了 IOBase。它處理位元組表示文字的流,並處理字串的編碼和解碼。TextIOWrapper,它擴充套件了 TextIOBase,是緩衝原始流 (BufferedIOBase) 的緩衝文字介面。最後,StringIO 是用於文字的記憶體流。

引數名稱不是規範的一部分,只有 open() 的引數才可以用作關鍵字引數。

下表總結了 io 模組提供的 ABC

ABC

繼承自

存根方法

混入方法和屬性

IOBase

fileno, seektruncate

close, closed, __enter__, __exit__, flush, isatty, __iter__, __next__, readable, readline, readlines, seekable, tell, writablewritelines

RawIOBase

IOBase

readintowrite

繼承的 IOBase 方法,readreadall

BufferedIOBase

IOBase

detach, read, read1write

繼承的 IOBase 方法, readintoreadinto1

TextIOBase

IOBase

detach, read, readlinewrite

繼承的 IOBase 方法, encoding, errorsnewlines

I/O 基類

class io.IOBase

所有 I/O 類的抽象基類。

此類為派生類可以選擇性覆蓋的許多方法提供了空的抽象實現;預設實現表示一個無法讀取、寫入或定位的檔案。

儘管 IOBase 沒有宣告 read()write() 因為它們的簽名會有所不同,但實現和客戶端應將這些方法視為介面的一部分。此外,當呼叫它們不支援的操作時,實現可能會引發 ValueError (或 UnsupportedOperation)。

從檔案讀取或寫入的二進位制資料基本型別是 bytes。其他 類位元組物件 也被接受為方法引數。文字 I/O 類使用 str 資料。

請注意,在關閉的流上呼叫任何方法(甚至查詢)都是未定義的。在這種情況下,實現可能會引發 ValueError

IOBase (及其子類) 支援迭代器協議,這意味著可以迭代 IOBase 物件,以生成流中的行。行的定義略有不同,具體取決於流是二進位制流(生成位元組)還是文字流(生成字串)。請參閱下面的 readline()

IOBase 也是一個上下文管理器,因此支援 with 語句。在此示例中,在 with 語句的套件完成後,即使發生異常,file 也會關閉

with open('spam.txt', 'w') as file:
    file.write('Spam and eggs!')

IOBase 提供以下資料屬性和方法

close()

重新整理並關閉此流。如果檔案已關閉,則此方法無效。檔案關閉後,對檔案的任何操作(例如讀取或寫入)都將引發 ValueError

為了方便起見,允許多次呼叫此方法;但是,只有第一次呼叫才有效。

closed

如果流已關閉,則為 True

fileno()

如果存在,則返回流的底層檔案描述符(一個整數)。如果 IO 物件不使用檔案描述符,則會引發 OSError

flush()

如果適用,則重新整理流的寫入緩衝區。這對只讀和非阻塞流沒有任何作用。

isatty()

如果流是互動式的(即,連線到終端/tty 裝置),則返回 True

readable()

如果可以從中讀取流,則返回 True。如果為 Falseread() 將引發 OSError

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,該 offset 相對於 whence 指示的位置進行解釋,並返回新的絕對位置。 whence 的值是:

  • os.SEEK_SET0 – 流的開始位置(預設);offset 應為零或正數

  • os.SEEK_CUR1 – 當前流位置;offset 可以為負數

  • os.SEEK_END2 – 流的末尾;offset 通常為負數

3.1 版本新增: SEEK_* 常量。

3.3 版本新增: 一些作業系統可能支援其他值,例如 os.SEEK_HOLEos.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, /)

將行列表寫入流。不會新增行分隔符,因此通常提供的每一行末尾都有一個行分隔符。

__del__()

準備物件銷燬。IOBase 提供了此方法的預設實現,該方法呼叫例項的 close() 方法。

class io.RawIOBase

原始二進位制流的基類。它繼承自 IOBase

原始二進位制流通常提供對底層作業系統裝置或 API 的低階訪問,並且不會嘗試將其封裝在高階原語中(此功能在緩衝的二進位制流和文字流的更高級別上完成,稍後在本頁中描述)。

RawIOBase 除了來自 IOBase 的方法之外,還提供這些方法:

read(size=-1, /)

從物件中讀取最多 size 個位元組並返回它們。為方便起見,如果未指定 size 或為 -1,則返回直到 EOF 的所有位元組。否則,只會進行一次系統呼叫。如果作業系統呼叫返回的位元組少於 size 個位元組,則可能返回少於 size 個位元組。

如果返回 0 個位元組,並且 size 不為 0,則表示檔案結束。如果物件處於非阻塞模式並且沒有可用的位元組,則返回 None

預設實現會延遲到 readall()readinto()

readall()

讀取並返回流中直到 EOF 的所有位元組,如有必要,可以使用對流的多次呼叫。

readinto(b, /)

將位元組讀取到預先分配的可寫 位元組類物件 b 中,並返回讀取的位元組數。例如,b 可能是 bytearray。如果物件處於非阻塞模式並且沒有可用的位元組,則返回 None

write(b, /)

將給定的 位元組類物件 b 寫入到底層原始流,並返回寫入的位元組數。這可能小於 b 的位元組長度,具體取決於底層原始流的特性,尤其是在它處於非阻塞模式的情況下。如果原始流設定為不阻塞,並且無法將其輕鬆寫入任何單個位元組,則返回 None。呼叫者可以在此方法返回後釋放或更改 b,因此實現應僅在方法呼叫期間訪問 b

class io.BufferedIOBase

支援某種緩衝的二進位制流的基類。它繼承自 IOBase

RawIOBase 的主要區別在於,方法 read()readinto()write() 將嘗試(分別)讀取請求的儘可能多的輸入或消耗所有給定的輸出,代價可能是進行多次系統呼叫。

此外,如果底層原始流處於非阻塞模式且無法獲取或提供足夠的資料,這些方法可能會引發 BlockingIOError 異常;與它們的 RawIOBase 對應方法不同,它們永遠不會返回 None

此外,read() 方法沒有預設實現來委託給 readinto()

一個典型的 BufferedIOBase 實現不應繼承自 RawIOBase 實現,而是應該像 BufferedWriterBufferedReader 那樣包裝一個。

BufferedIOBase 除了提供或覆蓋來自 IOBase 的資料屬性和方法外,還提供或覆蓋以下資料屬性和方法。

raw

BufferedIOBase 處理的底層原始流(RawIOBase 例項)。 這不是 BufferedIOBase API 的一部分,可能在某些實現中不存在。

detach()

將底層原始流與緩衝區分離並返回。

在分離原始流後,緩衝區處於不可用狀態。

某些緩衝區,如 BytesIO,沒有從該方法返回的單個原始流的概念。它們會引發 UnsupportedOperation 異常。

在 3.1 版本中新增。

read(size=-1, /)

讀取並返回最多 size 個位元組。如果省略該引數,或為 None 或負數,則會讀取並返回資料,直到到達 EOF。如果流已到達 EOF,則返回一個空的 bytes 物件。

如果引數為正數,並且底層原始流不是互動式的,則可能會發出多次原始讀取以滿足位元組計數(除非先到達 EOF)。但是對於互動式原始流,最多隻會發出一次原始讀取,並且結果較短並不意味著 EOF 即將到來。

如果底層原始流處於非阻塞模式,並且目前沒有可用資料,則會引發 BlockingIOError 異常。

read1(size=-1, /)

讀取並返回最多 size 個位元組,最多呼叫一次底層原始流的 read()(或 readinto())方法。如果您正在 BufferedIOBase 物件之上實現自己的緩衝,這將非常有用。

如果 size-1(預設值),則返回任意數量的位元組(除非到達 EOF,否則大於零)。

readinto(b, /)

將位元組讀取到預先分配的可寫 類位元組物件 b 中,並返回讀取的位元組數。例如,b 可以是一個 bytearray

read() 類似,可能會向底層原始流發出多次讀取,除非後者是互動式的。

如果底層原始流處於非阻塞模式,並且目前沒有可用資料,則會引發 BlockingIOError 異常。

readinto1(b, /)

使用最多一次呼叫底層原始流的 read()(或 readinto())方法,將位元組讀取到預先分配的可寫 類位元組物件 b 中。返回讀取的位元組數。

如果底層原始流處於非阻塞模式,並且目前沒有可用資料,則會引發 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 物件關閉時,此 fd 也將關閉,除非將 closefd 設定為 False

模式可以是 '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 除了來自 RawIOBaseIOBase 的屬性外,還提供以下資料屬性

mode

建構函式中給定的模式。

name

檔名。當建構函式中沒有給出名稱時,這是檔案的檔案描述符。

緩衝流

緩衝 I/O 流為 I/O 裝置提供了比原始 I/O 更高階的介面。

class io.BytesIO(initial_bytes=b'')

一個使用記憶體位元組緩衝區的二進位制流。它繼承自 BufferedIOBase。當呼叫 close() 方法時,緩衝區將被丟棄。

可選引數 initial_bytes 是一個 類位元組物件,其中包含初始資料。

BytesIO 除了來自 BufferedIOBaseIOBase 的方法外,還提供或覆蓋以下方法

getbuffer()

返回緩衝區內容的讀寫檢視,而無需複製它們。此外,更改檢視將透明地更新緩衝區的內容

>>> b = io.BytesIO(b"abcdef")
>>> view = b.getbuffer()
>>> view[2:4] = b"56"
>>> b.getvalue()
b'ab56ef'

注意

只要檢視存在,就不能調整 BytesIO 物件的大小或關閉它。

在 3.2 版本中新增。

getvalue()

返回 bytes,其中包含緩衝區的全部內容。

read1(size=-1, /)

BytesIO 中,這與 read() 相同。

在 3.7 版本中更改: size 引數現在是可選的。

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 除了來自 BufferedIOBaseIOBase 的方法外,還提供或覆蓋以下方法

peek(size=0, /)

從流返回位元組,而不推進位置。為了滿足呼叫,最多隻對原始流進行一次讀取。返回的位元組數可能少於或多於請求的位元組數。

read(size=-1, /)

讀取並返回 size 個位元組,如果未給定 size 或為負數,則讀取到 EOF 或如果讀取呼叫在非阻塞模式下會阻塞。

read1(size=-1, /)

讀取並返回最多 size 個位元組,僅對原始流進行一次呼叫。如果至少緩衝了一個位元組,則僅返回緩衝的位元組。否則,將進行一次原始流讀取呼叫。

在 3.7 版本中更改: size 引數現在是可選的。

class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)

一個緩衝的二進位制流,為可寫、不可查詢的 RawIOBase 原始二進位制流提供更高級別的訪問。它繼承自 BufferedIOBase

當寫入此物件時,資料通常會放入內部緩衝區中。在各種條件下,緩衝區將被寫出到底層的 RawIOBase 物件,包括:

建構函式為給定的可寫原始流建立一個 BufferedWriter。如果未給出buffer_size,則預設為 DEFAULT_BUFFER_SIZE

BufferedWriter 除了 BufferedIOBaseIOBase 的方法外,還提供或覆蓋了以下方法:

flush()

強制將緩衝區中儲存的位元組寫入原始流。如果原始流阻塞,則應引發 BlockingIOError 異常。

write(b, /)

寫入 位元組類物件b,並返回寫入的位元組數。在非阻塞模式下,如果緩衝區需要寫出但原始流阻塞,則會引發 BlockingIOError 異常。

class io.BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)

一個緩衝的二進位制流,提供對可查詢的 RawIOBase 原始二進位制流的高階訪問。它繼承自 BufferedReaderBufferedWriter

建構函式為可查詢的原始流建立一個讀取器和寫入器,該原始流在第一個引數中給出。如果省略了 buffer_size,則預設為 DEFAULT_BUFFER_SIZE

BufferedRandom 能夠執行 BufferedReaderBufferedWriter 可以做的任何事情。此外,保證實現 seek()tell()

class io.BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE, /)

一個緩衝的二進位制流,提供對兩個不可查詢的 RawIOBase 原始二進位制流(一個可讀,另一個可寫)的高階訪問。它繼承自 BufferedIOBase

readerwriterRawIOBase 物件,分別可讀和可寫。如果省略了 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 例項)。這不是 TextIOBase API 的一部分,並且可能在某些實現中不存在。

detach()

將底層二進位制緩衝區與 TextIOBase 分離並返回它。

分離底層緩衝區後,TextIOBase 處於不可用狀態。

一些 TextIOBase 實現(如 StringIO)可能沒有底層緩衝區的概念,呼叫此方法會引發 UnsupportedOperation 異常。

在 3.1 版本中新增。

read(size=-1, /)

從流中讀取並返回最多 size 個字元作為單個 str。如果 size 為負數或 None,則讀取到 EOF。

readline(size=-1, /)

讀取到換行符或 EOF 並返回單個 str。如果流已在 EOF,則返回空字串。

如果指定了 size,則最多讀取 size 個字元。

seek(offset, whence=SEEK_SET, /)

將流位置更改為給定的 offset。行為取決於 whence 引數。whence 的預設值為 SEEK_SET

  • SEEK_SET0:從流的開頭開始查詢(預設);offset 必須是 TextIOBase.tell() 返回的數字或零。任何其他 offset 值都會產生未定義的行為。

  • SEEK_CUR1: “seek” 到當前位置;offset 必須為零,這是一個空操作(不支援所有其他值)。

  • SEEK_END2: seek 到流的末尾;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 指定流將使用哪種編碼進行解碼或編碼。預設為 locale.getencoding()。 可以使用 encoding="locale" 來顯式指定當前區域設定的編碼。有關更多資訊,請參見 文字編碼

errors 是一個可選的字串,用於指定如何處理編碼和解碼錯誤。如果存在編碼錯誤,則傳遞 'strict' 來引發 ValueError 異常(None 的預設值具有相同的效果),或者傳遞 'ignore' 來忽略錯誤。(請注意,忽略編碼錯誤可能會導致資料丟失。) 'replace' 會在存在格式錯誤的資料時插入一個替換標記(例如 '?')。 'backslashreplace' 會將格式錯誤的資料替換為反斜槓轉義序列。寫入時,可以使用 'xmlcharrefreplace' (替換為適當的 XML 字元引用)或 'namereplace' (替換為 \N{...} 轉義序列)。任何其他已向 codecs.register_error() 註冊的錯誤處理名稱也是有效的。

newline 控制如何處理行尾。它可以是 None'''\n''\r''\r\n'。它的工作方式如下:

  • 從流中讀取輸入時,如果 newlineNone,則啟用 通用換行符 模式。輸入中的行可以以 '\n''\r''\r\n' 結尾,並且在返回給呼叫者之前,這些結尾會被轉換為 '\n'。如果 newline'',則啟用通用換行符模式,但行尾將以未轉換的形式返回給呼叫者。如果 newline 具有任何其他合法值,則輸入行僅以給定的字串結尾,並且行尾將以未轉換的形式返回給呼叫者。

  • 向流中寫入輸出時,如果 newlineNone,則任何寫入的 '\n' 字元都會被轉換為系統預設的行分隔符,即 os.linesep。如果 newline'''\n',則不會進行轉換。如果 newline 為任何其他合法值,則任何寫入的 '\n' 字元都將轉換為給定的字串。

如果 line_bufferingTrue,則當對 write 的呼叫包含換行符或回車符時,會隱式呼叫 flush()

如果 write_throughTrue,則保證對 write() 的呼叫不會被緩衝:在 TextIOWrapper 物件上寫入的任何資料都會立即傳遞到其底層的二進位制 buffer

在 3.3 版本中更改: 添加了 write_through 引數。

在 3.3 版本中更改: 預設的 encoding 現在是 locale.getpreferredencoding(False) 而不是 locale.getpreferredencoding()。不要臨時使用 locale.setlocale() 更改區域設定編碼,而是使用當前的區域設定編碼,而不是使用者首選的編碼。

在 3.10 版本中更改: encoding 引數現在支援 "locale" 虛擬編碼名稱。

TextIOWrapper 除了 TextIOBaseIOBase 中的屬性和方法外,還提供以下資料屬性和方法:

line_buffering

是否啟用了行緩衝。

write_through

寫入是否立即傳遞到底層的二進位制緩衝區。

在 3.7 版本中新增。

reconfigure(*, encoding=None, errors=None, newline=None, line_buffering=None, write_through=None)

使用 encodingerrorsnewlineline_bufferingwrite_through 的新設定重新配置此文字流。

未指定的引數將保留當前設定,但當指定 encoding 但未指定 errors 時,將使用 errors='strict'

如果已從流中讀取了一些資料,則無法更改編碼或換行符。另一方面,可以在寫入後更改編碼。

此方法在設定新引數之前會隱式重新整理流。

在 3.7 版本中新增。

在 3.11 版本中更改: 該方法支援 encoding="locale" 選項。

seek(cookie, whence=os.SEEK_SET, /)

設定流位置。將新的流位置作為 int 返回。

支援四種操作,由以下引數組合給出:

  • seek(0, SEEK_SET): 回到流的開頭。

  • seek(cookie, SEEK_SET): 恢復以前的位置;cookie 必須是 tell() 返回的數字。

  • seek(0, SEEK_END): 快進到流的末尾。

  • seek(0, SEEK_CUR): 使當前流位置保持不變。

任何其他引數組合都無效,可能會引發異常。

另請參閱

os.SEEK_SET, os.SEEK_CUR, 和 os.SEEK_END.

tell()

返回流位置,形式為不透明數字。 tell() 的返回值可以作為輸入提供給 seek(),用於恢復之前的流位置。

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 除了提供來自 TextIOBaseIOBase 的方法外,還提供了此方法

getvalue()

返回一個包含緩衝區全部內容的 str 。換行符的解碼方式與 read() 相同,儘管流位置不會改變。

用法示例

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

效能

本節討論提供的具體 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() 都非常慢。

然而,StringIO 是一個原生的記憶體 Unicode 容器,將表現出與 BytesIO 類似的速度。

多執行緒

FileIO 物件是執行緒安全的,其程度取決於它們包裝的作業系統呼叫(例如 Unix 下的 read(2) )的執行緒安全性。

二進位制緩衝物件(BufferedReaderBufferedWriterBufferedRandomBufferedRWPair 的例項)使用鎖來保護其內部結構;因此,可以安全地從多個執行緒同時呼叫它們。

TextIOWrapper 物件不是執行緒安全的。

可重入性

二進位制緩衝物件(BufferedReaderBufferedWriterBufferedRandomBufferedRWPair 的例項)不是可重入的。雖然在正常情況下不會發生可重入呼叫,但它們可能會因在 signal 處理程式中執行 I/O 而產生。如果一個執行緒試圖重新進入它已經在訪問的緩衝物件,則會引發 RuntimeError。請注意,這並不禁止不同的執行緒進入緩衝物件。

上述情況隱含地擴充套件到文字檔案,因為 open() 函式會在 TextIOWrapper 中包裝一個緩衝物件。這包括標準流,因此也會影響內建的 print() 函式。