io --- 處理流的核心工具?

源代碼: Lib/io.py


概述?

io 模塊提供了 Python 用于處理各種 I/O 類型的主要工具。三種主要的 I/O類型分別為: 文本 I/O, 二進(jìn)制 I/O原始 I/O。這些是泛型類型,有很多種后端存儲(chǔ)可以用在他們上面。一個(gè)隸屬于任何這些類型的具體對(duì)象被稱作 file object。 其他同類的術(shù)語(yǔ)還有 類文件對(duì)象。

獨(dú)立于其類別,每個(gè)具體流對(duì)象也將具有各種功能:它可以是只讀,只寫(xiě)或讀寫(xiě)。它還可以允許任意隨機(jī)訪問(wèn)(向前或向后尋找任何位置),或僅允許順序訪問(wèn)(例如在套接字或管道的情況下)。

所有流對(duì)提供給它們的數(shù)據(jù)類型都很敏感。例如將 str 對(duì)象給二進(jìn)制流的 write() 方法會(huì)引發(fā) TypeError。將 bytes 對(duì)象提供給文本流的 write() 方法也是如此。

在 3.3 版更改: 由于 IOError 現(xiàn)在是 OSError 的別名,因此用于引發(fā) IOError 的操作現(xiàn)在會(huì)引發(fā) OSError 。

文本 I/O?

文本I/O預(yù)期并生成 str 對(duì)象。這意味著,無(wú)論何時(shí)后臺(tái)存儲(chǔ)是由字節(jié)組成的(例如在文件的情況下),數(shù)據(jù)的編碼和解碼都是透明的,并且可以選擇轉(zhuǎn)換特定于平臺(tái)的換行符。

創(chuàng)建文本流的最簡(jiǎn)單方法是使用 open(),可以選擇指定編碼:

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

內(nèi)存中文本流也可以作為 StringIO 對(duì)象使用:

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

TextIOBase 的文檔中詳細(xì)描述了文本流的API

二進(jìn)制 I/O?

二進(jìn)制I/O(也稱為緩沖I/O)預(yù)期 bytes-like objects 并生成 bytes 對(duì)象。不執(zhí)行編碼、解碼或換行轉(zhuǎn)換。這種類型的流可以用于所有類型的非文本數(shù)據(jù),并且還可以在需要手動(dòng)控制文本數(shù)據(jù)的處理時(shí)使用。

創(chuàng)建二進(jìn)制流的最簡(jiǎn)單方法是使用 open(),并在模式字符串中指定 'b'

f = open("myfile.jpg", "rb")

內(nèi)存中二進(jìn)制流也可以作為 BytesIO 對(duì)象使用:

f = io.BytesIO(b"some initial binary data: \x00\x01")

BufferedIOBase 的文檔中詳細(xì)描述了二進(jìn)制流 API。

其他庫(kù)模塊可以提供額外的方式來(lái)創(chuàng)建文本或二進(jìn)制流。參見(jiàn) socket.socket.makefile() 的示例。

原始 I/O?

原始 I/O(也稱為 非緩沖 I/O)通常用作二進(jìn)制和文本流的低級(jí)構(gòu)建塊。用戶代碼直接操作原始流的用法非常罕見(jiàn)。不過(guò),可以通過(guò)在禁用緩沖的情況下以二進(jìn)制模式打開(kāi)文件來(lái)創(chuàng)建原始流:

f = open("myfile.jpg", "rb", buffering=0)

RawIOBase 的文檔中詳細(xì)描述了原始流的API

文本編碼格式?

The default encoding of TextIOWrapper and open() is locale-specific (locale.getencoding()).

但是,很多開(kāi)發(fā)者在打開(kāi)以 UTF-8 編碼的文本文件 (例如 JSON, TOML, Markdown 等等...) 時(shí)會(huì)忘記指定編碼格式,因?yàn)榇蠖鄶?shù) Unix 平臺(tái)默認(rèn)使用 UTF-8 語(yǔ)言區(qū)域。 這會(huì)導(dǎo)致各種錯(cuò)誤因?yàn)榇蠖鄶?shù) Windows 用戶的語(yǔ)言區(qū)域編碼格式并不是 UTF-8。 例如:

# May not work on Windows when non-ASCII characters in the file.
with open("README.md") as f:
    long_description = f.read()

此外,雖然暫時(shí)還沒(méi)有確定的計(jì)劃,但 Python 可能會(huì)在未來(lái)將默認(rèn)的文本文件編碼格式改為 UTF-8。

為此,強(qiáng)烈建議你在打開(kāi)文本文件時(shí)顯式地指定編碼格式。 如果你想要使用 UTF-8,請(qǐng)傳入 encoding="utf-8"。 要使用當(dāng)前語(yǔ)言區(qū)域的編碼格式,encoding="locale" 已在 Python 3.10 中被支持。

When you need to run existing code on Windows that attempts to open UTF-8 files using the default locale encoding, you can enable the UTF-8 mode. See UTF-8 mode on Windows.

選擇性的 EncodingWarning?

3.10 新版功能: 請(qǐng)參閱 PEP 597 了解詳情。

要找出哪里使用了默認(rèn)語(yǔ)言區(qū)域的編碼格式,你可以啟用 -X warn_default_encoding 命令行選項(xiàng)或設(shè)置 PYTHONWARNDEFAULTENCODING 環(huán)境變量,這將在使用默認(rèn)編碼格式時(shí)發(fā)出 EncodingWarning。

如果你提供了使用 open()TextIOWrapper 的 API 并將 encoding=None 作為形參傳入,你可以使用 text_encoding() 以便 API 的調(diào)用方在沒(méi)有傳入 encoding 的時(shí)候?qū)l(fā)出 EncodingWarning。 但是,對(duì)于新的 API 請(qǐng)考慮默認(rèn)就使用 UTF-8 (即 encoding="utf-8")。

高階模塊接口?

io.DEFAULT_BUFFER_SIZE?

包含模塊緩沖 I/O 類使用的默認(rèn)緩沖區(qū)大小的 int。 在可能的情況下 open() 將使用文件的 blksize(由 os.stat() 獲得)。

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

這是內(nèi)置的 open() 函數(shù)的別名。

open 附帶參數(shù) pathmode、flags 會(huì)引發(fā) 審計(jì)事件

io.open_code(path)?

'rb' 模式打開(kāi)提供的文件。如果目的是將文件內(nèi)容做為可執(zhí)行代碼,則應(yīng)使用此函數(shù)。

path 應(yīng)當(dāng)為 str 類型并且是一個(gè)絕對(duì)路徑。

此函數(shù)的行為可以由對(duì) PyFile_SetOpenCodeHook() 的先期調(diào)用所重載。 但是,如果 pathstr 類型并且是一個(gè)絕對(duì)路徑,open_code(path) 的行為應(yīng)當(dāng)總是與 open(path, 'rb') 一致。 重載此行為的目的是為了給文件附加額外的驗(yàn)證或預(yù)處理。

3.8 新版功能.

io.text_encoding(encoding, stacklevel=2, /)?

這是一個(gè)針對(duì)使用 open()TextIOWrapper 的可調(diào)用對(duì)象的輔助函數(shù)并且具有 encoding=None 形參。

This function returns encoding if it is not None. Otherwise, it returns "locale" or "utf-8" depending on UTF-8 Mode.

This function emits an EncodingWarning if sys.flags.warn_default_encoding is true and encoding is None. stacklevel specifies where the warning is emitted. For example:

def read_text(path, encoding=None):
    encoding = io.text_encoding(encoding)  # stacklevel=2
    with open(path, encoding) as f:
        return f.read()

在這個(gè)例子中,將為 read_text() 的調(diào)用方發(fā)出 EncodingWarning

請(qǐng)參閱 文本編碼格式 了解更多信息。

3.10 新版功能.

在 3.11 版更改: text_encoding() returns "utf-8" when UTF-8 mode is enabled and encoding is None.

exception io.BlockingIOError?

這是內(nèi)置的 BlockingIOError 異常的兼容性別名。

exception io.UnsupportedOperation?

在流上調(diào)用不支持的操作時(shí)引發(fā)的繼承 OSErrorValueError 的異常。

參見(jiàn)

sys

包含標(biāo)準(zhǔn)IO流: sys.stdin, sys.stdoutsys.stderr 。

類的層次結(jié)構(gòu)?

I/O 流被安排為按類的層次結(jié)構(gòu)實(shí)現(xiàn)。 首先是 抽象基類 (ABC),用于指定流的各種類別,然后是提供標(biāo)準(zhǔn)流實(shí)現(xiàn)的具體類。

備注

抽象基類還提供某些方法的默認(rèn)實(shí)現(xiàn),以幫助實(shí)現(xiàn)具體的流類。例如 BufferedIOBase 提供了 readinto()readline() 的未優(yōu)化實(shí)現(xiàn)。

I/O層次結(jié)構(gòu)的頂部是抽象基類 IOBase 。它定義了流的基本接口。但是請(qǐng)注意,對(duì)流的讀取和寫(xiě)入之間沒(méi)有分離。如果實(shí)現(xiàn)不支持指定的操作,則會(huì)引發(fā) UnsupportedOperation 。

抽象基類 RawIOBaseIOBase 的子類。它負(fù)責(zé)將字節(jié)讀取和寫(xiě)入流中。 RawIOBase 的子類 FileIO 提供計(jì)算機(jī)文件系統(tǒng)中文件的接口。

抽象基類 BufferedIOBase 繼承了 IOBase ,處理原始二進(jìn)制流( RawIOBase )上的緩沖。其子類 BufferedWriterBufferedReaderBufferedRWPair 分別緩沖可讀、可寫(xiě)以及可讀寫(xiě)的原始二進(jìn)制流。 BufferedRandom 提供了帶緩沖的可隨機(jī)訪問(wèn)流接口。 BufferedIOBase 的另一個(gè)子類 BytesIO 是內(nèi)存中字節(jié)流。

抽象基類 TextIOBase 繼承了 IOBase 。它處理可表示文本的流,并處理字符串的編碼和解碼。類 TextIOWrapper 繼承了 TextIOBase ,是原始緩沖流( BufferedIOBase )的緩沖文本接口。最后, StringIO 是文本的內(nèi)存流。

參數(shù)名不是規(guī)范的一部分,只有 open() 的參數(shù)才用作關(guān)鍵字參數(shù)。

下表總結(jié)了抽象基類提供的 io 模塊:

抽象基類

繼承

抽象方法

Mixin方法和屬性

IOBase

fileno, seek, 和 truncate

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

RawIOBase

IOBase

readintowrite

繼承 IOBase 方法, read, 和 readall

BufferedIOBase

IOBase

detach, read, read1, 和 write

繼承 IOBase 方法, readinto, 和 readinto1

TextIOBase

IOBase

detach, read, readline, 和 write

繼承 IOBase 方法, encoding, errors, 和 newlines

I/O 基類?

class io.IOBase?

The abstract base class for all I/O classes.

此類為許多方法提供了空的抽象實(shí)現(xiàn),派生類可以有選擇地重寫(xiě)。默認(rèn)實(shí)現(xiàn)代表一個(gè)無(wú)法讀取、寫(xiě)入或查找的文件。

盡管 IOBase 沒(méi)有聲明 read()write() ,因?yàn)樗鼈兊暮灻麜?huì)有所不同,但是實(shí)現(xiàn)和客戶端應(yīng)該將這些方法視為接口的一部分。此外,當(dāng)調(diào)用不支持的操作時(shí)可能會(huì)引發(fā) ValueError (或 UnsupportedOperation )。

從文件讀取或?qū)懭胛募亩M(jìn)制數(shù)據(jù)的基本類型為 bytes 。其他 bytes-like objects 也可以作為方法參數(shù)。文本I/O類使用 str 數(shù)據(jù)。

請(qǐng)注意,在關(guān)閉的流上調(diào)用任何方法(甚至查詢)都是未定義的(undefined)。在這種情況下,實(shí)現(xiàn)可能會(huì)引發(fā) ValueError

IOBase (及其子類)支持迭代器協(xié)議,這意味著可以迭代 IOBase 對(duì)象以產(chǎn)生流中的行。根據(jù)流是二進(jìn)制流(產(chǎn)生字節(jié))還是文本流(產(chǎn)生字符串),行的定義略有不同。請(qǐng)參見(jiàn)下面的 readline() 。

IOBase 也是一個(gè)上下文管理器,因此支持 with 語(yǔ)句。 在這個(gè)示例中,file 將在 with 語(yǔ)句塊執(zhí)行完成之后被關(guān)閉 --- 即使是發(fā)生了異常:

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

IOBase 提供以下數(shù)據(jù)屬性和方法:

close()?

刷新并關(guān)閉此流。如果文件已經(jīng)關(guān)閉,則此方法無(wú)效。文件關(guān)閉后,對(duì)文件的任何操作(例如讀取或?qū)懭耄┒紩?huì)引發(fā) ValueError 。

為方便起見(jiàn),允許多次調(diào)用此方法。但是,只有第一個(gè)調(diào)用才會(huì)生效。

closed?

如果流已關(guān)閉,則返回 True。

fileno()?

返回流的底層文件描述符(整數(shù))---如果存在。如果 IO 對(duì)象不使用文件描述符,則會(huì)引發(fā) OSError 。

flush()?

刷新流的寫(xiě)入緩沖區(qū)(如果適用)。這對(duì)只讀和非阻塞流不起作用。

isatty()?

如果流是交互式的(即連接到終端/tty設(shè)備),則返回 True 。

readable()?

如果可以讀取流,則返回 True 。否則為 False ,且 read() 將引發(fā) OSError 錯(cuò)誤。

readline(size=- 1, /)?

從流中讀取并返回一行。如果指定了 size,將至多讀取 size 個(gè)字節(jié)。

對(duì)于二進(jìn)制文件行結(jié)束符總是 b'\n';對(duì)于文本文件,可以用將 newline 參數(shù)傳給 open() 的方式來(lái)選擇要識(shí)別的行結(jié)束符。

readlines(hint=- 1, /)?

從流中讀取并返回包含多行的列表??梢灾付?hint 來(lái)控制要讀取的行數(shù):如果(以字節(jié)/字符數(shù)表示的)所有行的總大小超出了 hint 則將不會(huì)讀取更多的行。

0 或更小的 hint 值以及 None,會(huì)被視為沒(méi)有 hint。

請(qǐng)注意使用 for line in file: ... 就足夠?qū)ξ募?duì)象進(jìn)行迭代了,可以不必調(diào)用 file.readlines()。

seek(offset, whence=SEEK_SET, /)?

將流位置修改到給定的字節(jié) offset。 offset 將相對(duì)于由 whence 指定的位置進(jìn)行解析。 whence 的默認(rèn)值為 SEEK_SETwhence 的可用值有:

  • SEEK_SET0 -- 流的開(kāi)頭(默認(rèn)值);offset 應(yīng)為零或正值

  • SEEK_CUR or 1 -- 當(dāng)前流位置;offset 可以為負(fù)值

  • SEEK_END or 2 -- 流的末尾;offset 通常為負(fù)值

返回新的絕對(duì)位置。

3.1 新版功能: SEEK_* 常量.

3.3 新版功能: 某些操作系統(tǒng)還可支持其他的值,例如 os.SEEK_HOLEos.SEEK_DATA。特定文件的可用值還會(huì)取決于它是以文本還是二進(jìn)制模式打開(kāi)。

seekable()?

如果流支持隨機(jī)訪問(wèn)則返回 True。 如為 False,則 seek(), tell()truncate() 將引發(fā) OSError

tell()?

返回當(dāng)前流的位置。

truncate(size=None, /)?

將流的大小調(diào)整為給定的 size 個(gè)字節(jié)(如果未指定 size 則調(diào)整至當(dāng)前位置)。 當(dāng)前的流位置不變。 這個(gè)調(diào)整操作可擴(kuò)展或減小當(dāng)前文件大小。 在擴(kuò)展的情況下,新文件區(qū)域的內(nèi)容取決于具體平臺(tái)(在大多數(shù)系統(tǒng)上,額外的字節(jié)會(huì)填充為零)。 返回新的文件大小。

在 3.5 版更改: 現(xiàn)在Windows在擴(kuò)展時(shí)將文件填充為零。

writable()?

如果流支持寫(xiě)入則返回 True。 如為 False,則 write()truncate() 將引發(fā) OSError

writelines(lines, /)?

將行列表寫(xiě)入到流。 不會(huì)添加行分隔符,因此通常所提供的每一行都帶有末尾行分隔符。

__del__()?

為對(duì)象銷毀進(jìn)行準(zhǔn)備。 IOBase 提供了此方法的默認(rèn)實(shí)現(xiàn),該實(shí)現(xiàn)會(huì)調(diào)用實(shí)例的 close() 方法。

class io.RawIOBase?

Base class for raw binary streams. It inherits IOBase.

原始二進(jìn)制流通常會(huì)提供對(duì)下層 OS 設(shè)備或 API 的低層級(jí)訪問(wèn),而不是嘗試將其封裝到高層級(jí)的基元中(此功能是在更高層級(jí)的緩沖二進(jìn)制流和文本流中實(shí)現(xiàn)的,將在下文中描述)。

RawIOBaseIOBase 的現(xiàn)有成員以外還提供了下列方法:

read(size=- 1, /)?

從對(duì)象中讀取 size 個(gè)字節(jié)并將其返回。 作為一個(gè)便捷選項(xiàng),如果 size 未指定或?yàn)?-1,則返回所有字節(jié)直到 EOF。 在其他情況下,僅會(huì)執(zhí)行一次系統(tǒng)調(diào)用。 如果操作系統(tǒng)調(diào)用返回字節(jié)數(shù)少于 size 則此方法也可能返回少于 size 個(gè)字節(jié)。

如果返回 0 個(gè)字節(jié)而 size 不為零 0,這表明到達(dá)文件末尾。 如果處于非阻塞模式并且沒(méi)有更多字節(jié)可用,則返回 None。

默認(rèn)實(shí)現(xiàn)會(huì)轉(zhuǎn)至 readall()readinto()。

readall()?

從流中讀取并返回所有字節(jié)直到 EOF,如有必要將對(duì)流執(zhí)行多次調(diào)用。

readinto(b, /)?

將字節(jié)數(shù)據(jù)讀入預(yù)先分配的可寫(xiě) bytes-like object b,并返回所讀取的字節(jié)數(shù)。 例如,b 可以是一個(gè) bytearray。 如果對(duì)象處理非阻塞模式并且沒(méi)有更多字節(jié)可用,則返回 None。

write(b, /)?

將給定的 bytes-like object b 寫(xiě)入到下層的原始流,并返回所寫(xiě)入的字節(jié)數(shù)。 這可以少于 b 的總字節(jié)數(shù),具體取決于下層原始流的設(shè)定,特別是如果它處于非阻塞模式的話。 如果原始流設(shè)為非阻塞并且不能真正向其寫(xiě)入單個(gè)字節(jié)時(shí)則返回 None。 調(diào)用者可以在此方法返回后釋放或改變 b,因此該實(shí)現(xiàn)應(yīng)該僅在方法調(diào)用期間訪問(wèn) b。

class io.BufferedIOBase?

Base class for binary streams that support some kind of buffering. It inherits IOBase.

RawIOBase 的主要差別在于 read(), readinto()write() 等方法將(分別)嘗試按照要求讀取盡可能多的輸入或是耗盡所有給定的輸出,其代價(jià)是可能會(huì)執(zhí)行一次以上的系統(tǒng)調(diào)用。

除此之外,那些方法還可能引發(fā) BlockingIOError,如果下層的原始數(shù)據(jù)流處于非阻塞模式并且無(wú)法接受或給出足夠數(shù)據(jù)的話;不同于對(duì)應(yīng)的 RawIOBase 方法,它們將永遠(yuǎn)不會(huì)返回 None。

并且,read() 方法也沒(méi)有轉(zhuǎn)向 readinto() 的默認(rèn)實(shí)現(xiàn)。

典型的 BufferedIOBase 實(shí)現(xiàn)不應(yīng)當(dāng)繼承自 RawIOBase 實(shí)現(xiàn),而要包裝一個(gè)該實(shí)現(xiàn),正如 BufferedWriterBufferedReader 所做的那樣。

BufferedIOBaseIOBase 的現(xiàn)有成員以外還提供或重載了下列數(shù)據(jù)屬性和方法:

raw?

BufferedIOBase 處理的下層原始流 (RawIOBase 的實(shí)例)。 它不是 BufferedIOBase API 的組成部分并且不存在于某些實(shí)現(xiàn)中。

detach()?

從緩沖區(qū)分離出下層原始流并將其返回。

在原始流被分離之后,緩沖區(qū)將處于不可用的狀態(tài)。

某些緩沖區(qū)例如 BytesIO 并無(wú)可從此方法返回的單獨(dú)原始流的概念。 它們將會(huì)引發(fā) UnsupportedOperation

3.1 新版功能.

read(size=- 1, /)?

讀取并返回最多 size 個(gè)字節(jié)。 如果此參數(shù)被省略、為 None 或?yàn)樨?fù)值,則讀取并返回所有數(shù)據(jù)直到 EOF。 如果流已經(jīng)到達(dá) EOF 則返回一個(gè)空的 bytes 對(duì)象。

如果此參數(shù)為正值,并且下層原始流不可交互,則可能發(fā)起多個(gè)原始讀取以滿足字節(jié)計(jì)數(shù)(直至先遇到 EOF)。 但對(duì)于可交互原始流,則將至多發(fā)起一個(gè)原始讀取,并且簡(jiǎn)短的結(jié)果并不意味著已到達(dá) EOF。

BlockingIOError 會(huì)在下層原始流不處于阻塞模式,并且當(dāng)前沒(méi)有可用數(shù)據(jù)時(shí)被引發(fā)。

read1(size=- 1, /)?

通過(guò)至多一次對(duì)下層流的 read() (或 readinto()) 方法的調(diào)用讀取并返回至多 size 個(gè)字節(jié)。 這適用于在 BufferedIOBase 對(duì)象之上實(shí)現(xiàn)你自己的緩沖區(qū)的情況。

如果 size-1 (默認(rèn)值),則返回任意數(shù)量的字節(jié)(多于零字節(jié),除非已到達(dá) EOF)。

readinto(b, /)?

將字節(jié)數(shù)據(jù)讀入預(yù)先分配的可寫(xiě) bytes-like object b 并返回所讀取的字節(jié)數(shù)。 例如,b 可以是一個(gè) bytearray。

類似于 read(),可能對(duì)下層原始流發(fā)起多次讀取,除非后者為交互式。

BlockingIOError 會(huì)在下層原始流不處于阻塞模式,并且當(dāng)前沒(méi)有可用數(shù)據(jù)時(shí)被引發(fā)。

readinto1(b, /)?

將字節(jié)數(shù)據(jù)讀入預(yù)先分配的可寫(xiě) bytes-like object b,其中至多使用一次對(duì)下層原始流 read() (或 readinto()) 方法的調(diào)用。 返回所讀取的字節(jié)數(shù)。

BlockingIOError 會(huì)在下層原始流不處于阻塞模式,并且當(dāng)前沒(méi)有可用數(shù)據(jù)時(shí)被引發(fā)。

3.5 新版功能.

write(b, /)?

寫(xiě)入給定的 bytes-like object b,并返回寫(xiě)入的字節(jié)數(shù) (總是等于 b 的字節(jié)長(zhǎng)度,因?yàn)槿绻麑?xiě)入失敗則會(huì)引發(fā) OSError)。 根據(jù)具體實(shí)現(xiàn)的不同,這些字節(jié)可能被實(shí)際寫(xiě)入下層流,或是出于運(yùn)行效率和冗余等考慮而暫存于緩沖區(qū)。

當(dāng)處于非阻塞模式時(shí),如果需要將數(shù)據(jù)寫(xiě)入原始流但它無(wú)法在不阻塞的情況下接受所有數(shù)據(jù)則將引發(fā) BlockingIOError。

調(diào)用者可能會(huì)在此方法返回后釋放或改變 b,因此該實(shí)現(xiàn)應(yīng)當(dāng)僅在方法調(diào)用期間訪問(wèn) b。

原始文件 I/O?

class io.FileIO(name, mode='r', closefd=True, opener=None)?

代表一個(gè)包含字節(jié)數(shù)據(jù)的 OS 層級(jí)文件的原始二進(jìn)制流。 它繼承自 RawIOBase。

name 可以是以下兩項(xiàng)之一:

  • 代表將被打開(kāi)的文件路徑的字符串或 bytes 對(duì)象。 在此情況下 closefd 必須為 True (默認(rèn)值) 否則將會(huì)引發(fā)異常。

  • 代表一個(gè)現(xiàn)有 OS 層級(jí)文件描述符的號(hào)碼的整數(shù),作為結(jié)果的 FileIO 對(duì)象將可訪問(wèn)該文件。 當(dāng) FileIO 對(duì)象被關(guān)閉時(shí)此 fd 也將被關(guān)閉,除非 closefd 設(shè)為 False。

mode 可以為 'r', 'w', 'x''a' 分別表示讀取(默認(rèn)模式)、寫(xiě)入、獨(dú)占新建或添加。 如果以寫(xiě)入或添加模式打開(kāi)的文件不存在將自動(dòng)新建;當(dāng)以寫(xiě)入模式打開(kāi)時(shí)文件將先清空。 以新建模式打開(kāi)時(shí)如果文件已存在則將引發(fā) FileExistsError。 以新建模式打開(kāi)文件也意味著要寫(xiě)入,因此該模式的行為與 'w' 類似。 在模式中附帶 '+' 將允許同時(shí)讀取和寫(xiě)入。

該類的 read() (當(dāng)附帶正值參數(shù)調(diào)用時(shí)), readinto()write() 方法將只執(zhí)行一次系統(tǒng)調(diào)用。

可以通過(guò)傳入一個(gè)可調(diào)用對(duì)象作為 opener 來(lái)使用自定義文件打開(kāi)器。 然后通過(guò)調(diào)用 opener 并傳入 (name, flags) 來(lái)獲取文件對(duì)象所對(duì)應(yīng)的下層文件描述符。 opener 必須返回一個(gè)打開(kāi)文件描述符(傳入 os.open 作為 opener 的結(jié)果在功能上將與傳入 None 類似)。

新創(chuàng)建的文件是 不可繼承的

有關(guān) opener 參數(shù)的示例,請(qǐng)參見(jiàn)內(nèi)置函數(shù) open() 。

在 3.3 版更改: 增加了 opener 參數(shù)。增加了 'x' 模式。

在 3.4 版更改: 文件現(xiàn)在禁止繼承。

FileIO 在繼承自 RawIOBaseIOBase 的現(xiàn)有成員以外還提供了以下數(shù)據(jù)屬性和方法:

mode?

構(gòu)造函數(shù)中給定的模式。

name?

文件名。當(dāng)構(gòu)造函數(shù)中沒(méi)有給定名稱時(shí),這是文件的文件描述符。

緩沖流?

相比原始 I/O,緩沖 I/O 流提供了針對(duì) I/O 設(shè)備的更高層級(jí)接口。

class io.BytesIO(initial_bytes=b'')?

一個(gè)使用內(nèi)在字節(jié)緩沖區(qū)的二進(jìn)制流。 它繼承自 BufferedIOBase。 在 close() 方法被調(diào)用時(shí)將會(huì)丟棄緩沖區(qū)。

可選參數(shù) initial_bytes 是一個(gè)包含初始數(shù)據(jù)的 bytes-like object

BytesIO 在繼承自 BufferedIOBaseIOBase 的成員以外還提供或重載了下列方法:

getbuffer()?

返回一個(gè)對(duì)應(yīng)于緩沖區(qū)內(nèi)容的可讀寫(xiě)視圖而不必拷貝其數(shù)據(jù)。 此外,改變視圖將透明地更新緩沖區(qū)內(nèi)容:

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

備注

只要視圖保持存在,BytesIO 對(duì)象就無(wú)法被改變大小或關(guān)閉。

3.2 新版功能.

getvalue()?

返回包含整個(gè)緩沖區(qū)內(nèi)容的 bytes

read1(size=- 1, /)?

BytesIO 中,這與 read() 相同。

在 3.7 版更改: size 參數(shù)現(xiàn)在是可選的。

readinto1(b, /)?

BytesIO 中,這與 readinto() 相同。

3.5 新版功能.

class io.BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE)?

一個(gè)提供對(duì)可讀、不可查找的 RawIOBase 原始二進(jìn)制流的高層級(jí)訪問(wèn)的緩沖二進(jìn)制流。 它繼承自 BufferedIOBase

當(dāng)從此對(duì)象讀取數(shù)據(jù)時(shí),可能會(huì)從下層原始流請(qǐng)求更大量的數(shù)據(jù),并存放到內(nèi)部緩沖區(qū)中。 接下來(lái)可以在后續(xù)讀取時(shí)直接返回緩沖數(shù)據(jù)。

根據(jù)給定的可讀 raw 流和 buffer_size 創(chuàng)建 BufferedReader 的構(gòu)造器。 如果省略 buffer_size,則會(huì)使用 DEFAULT_BUFFER_SIZE。

BufferedReader 在繼承自 BufferedIOBaseIOBase 的成員以外還提供或重載了下列方法:

peek(size=0, /)?

從流返回字節(jié)數(shù)據(jù)而不前移位置。 完成此調(diào)用將至多讀取一次原始流。 返回的字節(jié)數(shù)量可能少于或多于請(qǐng)求的數(shù)量。

read(size=- 1, /)?

讀取并返回 size 個(gè)字節(jié),如果 size 未給定或?yàn)樨?fù)值,則讀取至 EOF 或是在非阻塞模式下讀取調(diào)用將會(huì)阻塞。

read1(size=- 1, /)?

在原始流上通過(guò)單次調(diào)用讀取并返回至多 size 個(gè)字節(jié)。 如果至少緩沖了一個(gè)字節(jié),則只返回緩沖的字節(jié)。 在其他情況下,將執(zhí)行一次原始流讀取。

在 3.7 版更改: size 參數(shù)現(xiàn)在是可選的。

class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)?

一個(gè)提供對(duì)可寫(xiě)、不可查找的 RawIOBase 原始二進(jìn)制流的高層級(jí)訪問(wèn)的緩沖二進(jìn)制流。 它繼承自 BufferedIOBase。

當(dāng)寫(xiě)入到此對(duì)象時(shí),數(shù)據(jù)通常會(huì)被放入到內(nèi)部緩沖區(qū)中。 緩沖區(qū)將在滿足某些條件的情況下被寫(xiě)到下層的 RawIOBase 對(duì)象,包括:

  • 當(dāng)緩沖區(qū)對(duì)于所有掛起數(shù)據(jù)而言太小時(shí);

  • 當(dāng) flush() 被調(diào)用時(shí)

  • 當(dāng)(為 BufferedRandom 對(duì)象)請(qǐng)求 seek() 時(shí);

  • 當(dāng) BufferedWriter 對(duì)象被關(guān)閉或銷毀時(shí)。

該構(gòu)造器會(huì)為給定的可寫(xiě) raw 流創(chuàng)建一個(gè) BufferedWriter。 如果未給定 buffer_size,則使用默認(rèn)的 DEFAULT_BUFFER_SIZE。

BufferedWriter 在繼承自 BufferedIOBaseIOBase 的成員以外還提供或重載了下列方法:

flush()?

將緩沖區(qū)中保存的字節(jié)數(shù)據(jù)強(qiáng)制放入原始流。 如果原始流發(fā)生阻塞則應(yīng)當(dāng)引發(fā) BlockingIOError。

write(b, /)?

寫(xiě)入 bytes-like object b 并返回寫(xiě)入的字節(jié)數(shù)。 當(dāng)處于非阻塞模式時(shí),如果緩沖區(qū)需要被寫(xiě)入但原始流發(fā)生阻塞則將引發(fā) BlockingIOError。

class io.BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)?

一個(gè)提供對(duì)不可查找的 RawIOBase 原始二進(jìn)制流的高層級(jí)訪問(wèn)的緩沖二進(jìn)制流。 它繼承自 BufferedReaderBufferedWriter。

該構(gòu)造器會(huì)為在第一個(gè)參數(shù)中給定的可查找原始流創(chuàng)建一個(gè)讀取器和寫(xiě)入器。 如果省略 buffer_size 則使用默認(rèn)的 DEFAULT_BUFFER_SIZE。

BufferedRandom 能做到 BufferedReaderBufferedWriter 所能做的任何事。 此外,還會(huì)確保實(shí)現(xiàn) seek()tell()。

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

一個(gè)提供對(duì)兩個(gè)不可查找的 RawIOBase 原始二進(jìn)制流的高層級(jí)訪問(wèn)的緩沖二進(jìn)制流 --- 一個(gè)可讀,另一個(gè)可寫(xiě)。 它繼承自 BufferedIOBase。

readerwriter 分別是可讀和可寫(xiě)的 RawIOBase 對(duì)象。 如果省略 buffer_size 則使用默認(rèn)的 DEFAULT_BUFFER_SIZE。

BufferedRWPair 實(shí)現(xiàn)了 BufferedIOBase 的所有方法,但 detach() 除外,調(diào)用該方法將引發(fā) UnsupportedOperation

警告

BufferedRWPair 不會(huì)嘗試同步訪問(wèn)其下層的原始流。 你不應(yīng)當(dāng)將傳給它與讀取器和寫(xiě)入器相同的對(duì)象;而要改用 BufferedRandom

文本 I/O?

class io.TextIOBase?

Base class for text streams. This class provides a character and line based interface to stream I/O. It inherits IOBase.

TextIOBase 在來(lái)自 IOBase 的成員以外還提供或重載了以下數(shù)據(jù)屬性和方法:

encoding?

用于將流的字節(jié)串解碼為字符串以及將字符串編碼為字節(jié)串的編碼格式名稱。

errors?

解碼器或編碼器的錯(cuò)誤設(shè)置。

newlines?

一個(gè)字符串、字符串元組或者 None,表示目前已經(jīng)轉(zhuǎn)寫(xiě)的新行。 根據(jù)具體實(shí)現(xiàn)和初始構(gòu)造器旗標(biāo)的不同,此屬性或許會(huì)不可用。

buffer?

TextIOBase 處理的下層二進(jìn)制緩沖區(qū)(為一個(gè) BufferedIOBase 的實(shí)例)。 它不是 TextIOBase API 的組成部分并且不存在于某些實(shí)現(xiàn)中。

detach()?

TextIOBase 分離出下層二進(jìn)制緩沖區(qū)并將其返回。

在下層緩沖區(qū)被分離后,TextIOBase 將處于不可用的狀態(tài)。

某些 TextIOBase 的實(shí)現(xiàn),例如 StringIO 可能并無(wú)下層緩沖區(qū)的概念,因此調(diào)用此方法將引發(fā) UnsupportedOperation。

3.1 新版功能.

read(size=- 1, /)?

從流中讀取至多 size 個(gè)字符并以單個(gè) str 的形式返回。 如果 size 為負(fù)值或 None,則讀取至 EOF。

readline(size=- 1, /)?

讀取至換行符或 EOF 并返回單個(gè) str。 如果流已經(jīng)到達(dá) EOF,則將返回一個(gè)空字符串。

如果指定了 size ,最多將讀取 size 個(gè)字符。

seek(offset, whence=SEEK_SET, /)?

將流位置改為給定的偏移位置 offset。 具體行為取決于 whence 形參。 whence 的默認(rèn)值為 SEEK_SET

  • SEEK_SET0: 從流的開(kāi)始位置起查找(默認(rèn)值);offset 必須為 TextIOBase.tell() 所返回的數(shù)值或?yàn)榱恪?任何其他 offset 值都將導(dǎo)致未定義的行為。

  • SEEK_CUR1: "查找" 到當(dāng)前位置;offset 必須為零,表示無(wú)操作(所有其他值均不受支持)。

  • SEEK_END2: 查找到流的末尾;offset 必須為零(所有其他值均不受支持)。

以不透明數(shù)字形式返回新的絕對(duì)位置。

3.1 新版功能: SEEK_* 常量.

tell()?

以不透明數(shù)字形式返回當(dāng)前流的位置。 該數(shù)字通常并不代表下層二進(jìn)制存儲(chǔ)中對(duì)應(yīng)的字節(jié)數(shù)。

write(s, /)?

將字符串 s 寫(xiě)入到流并返回寫(xiě)入的字符數(shù)。

class io.TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False)?

一個(gè)提供對(duì) BufferedIOBase 緩沖二進(jìn)制流的高層級(jí)訪問(wèn)的緩沖文本流。 它繼承自 TextIOBase。

encoding gives the name of the encoding that the stream will be decoded or encoded with. It defaults to locale.getencoding(). encoding="locale" can be used to specify the current locale's encoding explicitly. See 文本編碼格式 for more information.

errors 是一個(gè)可選的字符串,它指明編碼格式和編碼格式錯(cuò)誤的處理方式。 傳入 'strict' 將在出現(xiàn)編碼格式錯(cuò)誤時(shí)引發(fā) ValueError (默認(rèn)值 None 具有相同的效果),傳入 'ignore' 將忽略錯(cuò)誤。 (請(qǐng)注意忽略編碼格式錯(cuò)誤會(huì)導(dǎo)致數(shù)據(jù)丟失。) 'replace' 會(huì)在出現(xiàn)錯(cuò)誤數(shù)據(jù)時(shí)插入一個(gè)替換標(biāo)記 (例如 '?')。 'backslashreplace' 將把錯(cuò)誤數(shù)據(jù)替換為一個(gè)反斜杠轉(zhuǎn)義序列。 在寫(xiě)入時(shí),還可以使用 'xmlcharrefreplace' (替換為適當(dāng)?shù)?XML 字符引用) 或 'namereplace' (替換為 \N{...} 轉(zhuǎn)義序列)。 任何其他通過(guò) codecs.register_error() 注冊(cè)的錯(cuò)誤處理方式名稱也可以被接受。

newline 控制行結(jié)束符處理方式。 它可以為 None, '', '\n', '\r''\r\n'。 其工作原理如下:

  • 當(dāng)從流讀取輸入時(shí),如果 newlineNone,則將啟用 universal newlines 模式。 輸入中的行結(jié)束符可以為 '\n', '\r''\r\n',在返回給調(diào)用者之前它們會(huì)被統(tǒng)一轉(zhuǎn)寫(xiě)為 '\n'。 如果 newline'',也會(huì)啟用通用換行模式,但行結(jié)束符會(huì)不加轉(zhuǎn)寫(xiě)即返回給調(diào)用者。 如果 newline 具有任何其他合法的值,則輸入行將僅由給定的字符串結(jié)束,并且行結(jié)束符會(huì)不加轉(zhuǎn)寫(xiě)即返回給調(diào)用者。

  • 將輸出寫(xiě)入流時(shí),如果 newlineNone,則寫(xiě)入的任何 '\n' 字符都將轉(zhuǎn)換為系統(tǒng)默認(rèn)行分隔符 os.linesep。如果 newline'''\n',則不進(jìn)行翻譯。如果 newline 是任何其他合法值,則寫(xiě)入的任何 '\n' 字符將被轉(zhuǎn)換為給定的字符串。

如果 line_bufferingTrue,則當(dāng)一個(gè)寫(xiě)入調(diào)用包含換行符或回車時(shí)將會(huì)應(yīng)用 flush()。

如果 write_throughTrue,對(duì) write() 的調(diào)用會(huì)確保不被緩沖:在 TextIOWrapper 對(duì)象上寫(xiě)入的任何數(shù)據(jù)會(huì)立即交給其下層的 buffer 來(lái)處理。

在 3.3 版更改: 已添加 write_through 參數(shù)

在 3.3 版更改: 默認(rèn)的 encoding 現(xiàn)在將為 locale.getpreferredencoding(False) 而非 locale.getpreferredencoding()。 不要使用 locale.setlocale() 來(lái)臨時(shí)改變區(qū)域編碼格式,要使用當(dāng)前區(qū)域編碼格式而不是用戶的首選編碼格式。

在 3.10 版更改: encoding 參數(shù)現(xiàn)在支持 "locale" 作為編碼格式名稱。

TextIOWrapper 在繼承自 TextIOBaseIOBase 的現(xiàn)有成員以外還提供了以下數(shù)據(jù)屬性和方法:

line_buffering?

是否啟用行緩沖。

write_through?

寫(xiě)入是否要立即傳給下層的二進(jìn)制緩沖。

3.7 新版功能.

reconfigure(*[, encoding][, errors][, newline][,                      line_buffering][, write_through])?

使用 encoding, errors, newline, line_bufferingwrite_through 的新設(shè)置來(lái)重新配置此文本流。

未指定的形參將保留當(dāng)前設(shè)定,例外情況是當(dāng)指定了 encoding 但未指定 errors 時(shí)將會(huì)使用 errors='strict'。

如果已經(jīng)有數(shù)據(jù)從流中被讀取則將無(wú)法再改變編碼格式或行結(jié)束符。 另一方面,在寫(xiě)入數(shù)據(jù)之后再改變編碼格式則是可以的。

此方法會(huì)在設(shè)置新的形參之前執(zhí)行隱式的流刷新。

3.7 新版功能.

在 3.11 版更改: The method supports encoding="locale" option.

class io.StringIO(initial_value='', newline='\n')?

一個(gè)使用內(nèi)存文本緩沖的文本流。 它繼承自 TextIOBase。

當(dāng) close() 方法被調(diào)用時(shí)將會(huì)丟棄文本緩沖區(qū)。

緩沖區(qū)的初始值可通過(guò)提供 initial_value 來(lái)設(shè)置。 如果啟用了行結(jié)束符轉(zhuǎn)寫(xiě),換行將以 write() 所用的方式被編碼。 數(shù)據(jù)流位置將被設(shè)為緩沖區(qū)的開(kāi)頭。

newline 參數(shù)的規(guī)則與 TextIOWrapper 所用的一致,不同之處在于當(dāng)將輸出寫(xiě)入到流時(shí),如果 newlineNone,則在所有平臺(tái)上換行符都會(huì)被寫(xiě)入為 \n。

StringIO 在繼承自 TextIOBaseIOBase 的現(xiàn)有成員以外還提供了以下方法:

getvalue()?

返回一個(gè)包含緩沖區(qū)全部?jī)?nèi)容的 str。 換行符會(huì)以與 read() 相同的方式被編碼,但是流的位置不會(huì)被改變。

用法示例:

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?

用于在 universal newlines 模式下解碼換行符的輔助編解碼器。 它繼承自 codecs.IncrementalDecoder。

性能?

本節(jié)討論所提供的具體 I/O 實(shí)現(xiàn)的性能。

二進(jìn)制 I/O?

即使在用戶請(qǐng)求單個(gè)字節(jié)時(shí),也只讀取和寫(xiě)入大塊數(shù)據(jù)。通過(guò)該方法,緩沖 I/O 隱藏了操作系統(tǒng)調(diào)用和執(zhí)行無(wú)緩沖 I/O 例程時(shí)的任何低效性。增益取決于操作系統(tǒng)和執(zhí)行的 I/O 類型。例如,在某些現(xiàn)代操作系統(tǒng)上(例如 Linux),無(wú)緩沖磁盤(pán) I/O 可以與緩沖 I/O 一樣快。但最重要的是,無(wú)論平臺(tái)和支持設(shè)備如何,緩沖 I/O 都能提供可預(yù)測(cè)的性能。因此,對(duì)于二進(jìn)制數(shù)據(jù),應(yīng)首選使用緩沖的 I/O 而不是未緩沖的 I/O 。

文本 I/O?

二進(jìn)制存儲(chǔ)(如文件)上的文本 I/O 比同一存儲(chǔ)上的二進(jìn)制 I/O 慢得多,因?yàn)樗枰褂米址幗獯a器在Unicode和二進(jìn)制數(shù)據(jù)之間進(jìn)行轉(zhuǎn)換。這在處理大量文本數(shù)據(jù)(如大型日志文件)時(shí)會(huì)變得非常明顯。此外,由于使用的重構(gòu)算法 TextIOWrapper.tell()TextIOWrapper.seek() 都相當(dāng)慢。

StringIO 是原生的內(nèi)存 Unicode 容器,速度與 BytesIO 相似。

多線程?

FileIO 對(duì)象是線程安全的,只要它們封裝的操作系統(tǒng)調(diào)用(比如Unix下的 read(2) )也是線程安全的。

二進(jìn)制緩沖對(duì)象(例如 BufferedReader, BufferedWriter, BufferedRandomBufferedRWPair)使用鎖來(lái)保護(hù)其內(nèi)部結(jié)構(gòu);因此,可以安全地一次從多個(gè)線程中調(diào)用它們。

TextIOWrapper 對(duì)象不再是線程安全的。

可重入性?

二進(jìn)制緩沖對(duì)象( BufferedReader , BufferedWriter , BufferedRandomBufferedRWPair 的實(shí)例)不是可重入的。雖然在正常情況下不會(huì)發(fā)生可重入調(diào)用,但仍可能會(huì)在 signal 處理程序執(zhí)行 I/O 時(shí)產(chǎn)生。如果線程嘗試重入已經(jīng)訪問(wèn)的緩沖對(duì)象,則會(huì)引發(fā) RuntimeError 。注意,這并不禁止其他線程進(jìn)入緩沖對(duì)象。

上面的內(nèi)容隱式地?cái)U(kuò)展到文本文件中,因?yàn)?open() 函數(shù)將把緩沖對(duì)象封裝在 TextIOWrapper 中。 這包括標(biāo)準(zhǔn)流,因而也會(huì)影響內(nèi)置的 print() 函數(shù)。