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() 函数。