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")
文本流 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 区域设置。这会导致错误,因为大多数 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.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
为 true 且 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 流的实现组织为类层次结构。 首先是 抽象基类 (ABCs),用于指定各种类别的流,然后是提供标准流实现的具体类。
注意
抽象基类还提供一些方法的默认实现,以帮助实现具体的流类。例如,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 |
继承自 |
存根方法 |
混入方法和属性 |
---|---|---|---|
|
|
||
|
继承的 |
||
|
继承的 |
||
|
继承的 |
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
。
- 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,该 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()
将尝试(分别)读取请求的尽可能多的输入或消耗所有给定的输出,代价可能是进行多次系统调用。此外,如果底层原始流处于非阻塞模式且无法获取或提供足够的数据,这些方法可能会引发
BlockingIOError
异常;与它们的RawIOBase
对应方法不同,它们永远不会返回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。如果流已到达 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
除了来自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, /)¶
读取并返回 size 个字节,如果未给定 size 或为负数,则读取到 EOF 或如果读取调用在非阻塞模式下会阻塞。
- read1(size=-1, /)¶
读取并返回最多 size 个字节,仅对原始流进行一次调用。如果至少缓冲了一个字节,则仅返回缓冲的字节。否则,将进行一次原始流读取调用。
在 3.7 版本中更改: size 参数现在是可选的。
- class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)¶
一个缓冲的二进制流,为可写、不可查找的
RawIOBase
原始二进制流提供更高级别的访问。它继承自BufferedIOBase
。当写入此对象时,数据通常会放入内部缓冲区中。在各种条件下,缓冲区将被写出到底层的
RawIOBase
对象,包括:当缓冲区对于所有待处理数据来说太小时;
当调用
flush()
时;当请求
seek()
时(对于BufferedRandom
对象);当
BufferedWriter
对象关闭或销毁时。
构造函数为给定的可写原始流创建一个
BufferedWriter
。如果未给出buffer_size,则默认为DEFAULT_BUFFER_SIZE
。BufferedWriter
除了BufferedIOBase
和IOBase
的方法外,还提供或覆盖了以下方法:- flush()¶
强制将缓冲区中保存的字节写入原始流。如果原始流阻塞,则应引发
BlockingIOError
异常。
- write(b, /)¶
写入 字节类对象b,并返回写入的字节数。在非阻塞模式下,如果缓冲区需要写出但原始流阻塞,则会引发
BlockingIOError
异常。
- 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
实例)。这不是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
: “seek” 到当前位置;offset 必须为零,这是一个空操作(不支持所有其他值)。SEEK_END
或2
: 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'
。它的工作方式如下:从流中读取输入时,如果 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"
虚拟编码名称。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
。
性能¶
本节讨论提供的具体 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()
函数。