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")

备注

当使用非阻塞流时,请注意,如果流无法立即执行操作,对文本 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 的文档中有详细描述。

文本编码

TextIOWrapperopen() 的默认编码是与区域设置相关的(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.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 为真且 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 流的实现被组织成一个类的层次结构。首先是抽象基类 (ABC),它们用于指定流的各种类别,然后是提供标准流实现的具体类。

备注

抽象基类还为某些方法提供了默认实现,以帮助实现具体的流类。例如,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 (抽象基类)

继承自

存根方法 (Stub Methods)

混入方法和属性 (Mixin Methods and Properties)

IOBase

fileno, seek, 和 truncate

close, closed, __enter__, __exit__, flush, isatty, __iter__, __next__, readable, readline, readlines, seekable, tell, writable, 和 writelines

RawIOBase

IOBase

readintowrite

继承自 IOBase 的方法、readreadall

BufferedIOBase

IOBase

detach, read, read1, 和 write

继承自 IOBase 的方法、readintoreadinto1

TextIOBase

IOBase

detach, read, readline, 和 write

继承自 IOBase 的方法、encoding, errors, 和 newlines

I/O 基类

class io.IOBase

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

这个类为许多方法提供了空的抽象实现,派生类可以有选择地覆盖这些实现;默认实现代表了一个不可读、不可写或不可查找的文件。

尽管 IOBase 没有声明 read()write(),因为它们的签名会变化,但实现和客户端应将这些方法视为接口的一部分。此外,当调用不支持的操作时,实现可能会引发 ValueError(或 UnsupportedOperation)。

从文件中读取或写入文件的二进制数据的基本类型是 bytes。其他类字节对象也可用作方法参数。文本 I/O 类处理 str 数据。

请注意,对一个已关闭的流调用任何方法(甚至是查询)都是未定义的。在这种情况下,实现可能会引发 ValueError

IOBase(及其子类)支持迭代器协议,这意味着可以对 IOBase 对象进行迭代,以产生流中的行。行的定义略有不同,取决于流是二进制流(产生字节)还是文本流(产生字符串)。请参阅下面的 readline()

IOBase 也是一个上下文管理器,因此支持 with 语句。在此示例中,filewith 语句块完成后被关闭——即使发生异常也是如此:

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,相对于 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。如果为 Falseseek()tell()truncate() 将引发 OSError

tell()

返回当前流的位置。

truncate(size=None, /)

将流的大小调整为给定的 size 字节(如果未指定 size,则为当前位置)。当前流的位置不变。此调整大小可以扩展或缩小当前文件大小。在扩展的情况下,新文件区域的内容取决于平台(在大多数系统上,额外的字节用零填充)。返回新的文件大小。

在 3.5 版更改: 现在,Windows 在扩展文件时会用零填充。

writable()

如果流支持写入,则返回 True。如果为 Falsewrite()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() 将(分别)尝试读取请求的全部输入或发出所有提供的数据。

此外,如果底层原始流处于非阻塞模式,当系统返回会阻塞时,write() 将引发 BlockingIOError 并带有 BlockingIOError.characters_written 属性,而 read() 将返回已读取的数据,或者如果没有可用数据则返回 None

此外,read() 方法没有一个委托给 readinto() 的默认实现。

一个典型的 BufferedIOBase 实现不应该继承自 RawIOBase 实现,而是包装一个,就像 BufferedWriterBufferedReader 所做的那样。

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 或返回 Noneio 实现返回 None

read1(size=-1, /)

读取并返回最多 size 个字节,调用 readinto(),根据 PEP 475 的规定,如果遇到 EINTR 可能会重试。如果 size-1 或未提供,实现将为 size 选择一个任意值。

备注

当底层原始流是非阻塞时,实现可能会在没有可用数据时引发 BlockingIOError 或返回 Noneio 实现返回 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 除了 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, /)

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 对象中,包括:

构造函数为给定的可写 raw 流创建一个 BufferedWriter。如果未指定 buffer_size,则默认为 DEFAULT_BUFFER_SIZE

BufferedWriterBufferedIOBaseIOBase 的方法之外,还提供或重写了以下方法:

flush()

强制将缓冲区中保留的字节写入原始流。如果原始流阻塞,则应引发 BlockingIOError

write(b, /)

写入 类字节对象 b,并返回写入的字节数。在非阻塞模式下,如果缓冲区需要写出但原始流阻塞,则会引发 BlockingIOError,并设置其 BlockingIOError.characters_written 属性。

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

readerwriter 是分别是可读和可写的 RawIOBase 对象。如果省略了 buffer_size,则默认为 DEFAULT_BUFFER_SIZE

BufferedRWPair 实现了 BufferedIOBase 的所有方法,除了 detach() 会引发 UnsupportedOperation

警告

BufferedRWPair 不会尝试同步对其底层原始流的访问。你不应该将同一个对象同时作为读取器和写入器传递给它;应改用 BufferedRandom

文本 I/O

class io.TextIOBase

文本流的基类。此类为流 I/O 提供了基于字符和行的接口。它继承自 IOBase

TextIOBaseIOBase 的基础上提供或重写了以下数据属性和方法:

encoding

用于将流的字节解码为字符串,以及将字符串编码为字节的编码名称。

errors

解码器或编码器的错误设置。

newlines

一个字符串、一个字符串元组或 None,表示迄今为止已转换的换行符。根据实现和初始构造函数标志,此属性可能不可用。

buffer

TextIOBase 处理的底层二进制缓冲区(一个 BufferedIOBaseRawIOBase 实例)。这不是 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:“查找”到当前位置;offset 必须为零,这是一个无操作(所有其他值都不支持)。

  • SEEK_END2:查找到流的末尾;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'。它的工作方式如下:

  • 从流中读取输入时,如果 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" 这个伪编码名称。

备注

当底层原始流是非阻塞时,如果读取操作无法立即完成,可能会引发 BlockingIOError

TextIOWrapperTextIOBaseIOBase 的基础上提供了以下数据属性和方法:

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):保持当前流位置不变。

任何其他参数组合都是无效的,可能会引发异常。

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 类似,但在向流中写入输出时,如果 newlineNone,则在所有平台上换行符都写为 \n

StringIOTextIOBaseIOBase 的基础上提供了以下方法:

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

静态类型

以下协议可用于为简单的流读取或写入操作的函数和方法参数添加注解。它们都使用了 @typing.runtime_checkable 装饰器。

class io.Reader[T]

用于从文件或其他输入流读取的通用协议。T 通常是 strbytes,但也可以是从流中读取的任何类型。

在 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 通常是 strbytes,但也可以是任何可以写入流中的类型。

在 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() 都相当慢。

然而,StringIO 是一个原生的内存中 Unicode 容器,其速度与 BytesIO 相似。

多线程

FileIO 对象是线程安全的,前提是它们所包装的操作系统调用(例如在 Unix 下的 read(2))也是线程安全的。

二进制缓冲对象(BufferedReaderBufferedWriterBufferedRandomBufferedRWPair 的实例)使用锁来保护其内部结构;因此,可以安全地从多个线程同时调用它们。

TextIOWrapper 对象不是线程安全的。

可重入性

二进制缓冲对象(BufferedReaderBufferedWriterBufferedRandomBufferedRWPair 的实例)是不可重入的。虽然在正常情况下不会发生可重入调用,但在 signal 处理程序中进行 I/O 操作时可能会出现。如果一个线程试图重新进入它已经在访问的缓冲对象,会引发 RuntimeError。注意,这并不禁止另一个线程进入该缓冲对象。

以上内容也隐式地扩展到文本文件,因为 open() 函数会将一个缓冲对象包装在 TextIOWrapper 内部。这包括标准流,因此也影响了内置的 print() 函数。