io
- 用于处理流的核心工具¶
源代码: Lib/io.py
概述¶
io
模块提供了 Python 处理各种 I/O 的主要工具。I/O 主要有三种类型:*文本 I/O*、*二进制 I/O* 和 *原始 I/O*。这些是通用类别,每种类别都可以使用各种后备存储。属于这些类别中的任何一个的具体对象称为 文件对象。其他常用术语是 *流* 和 *类文件对象*。
每个具体的流对象,无论属于哪个类别,都具有一些功能:它可以是只读的、只写的,或者可读写的。它还可以允许任意随机访问(向前或向后查找任何位置),或者只允许顺序访问(例如在套接字或管道的情况下)。
所有流都非常注意你提供给它们的数据类型。例如,将一个 str
对象传递给二进制流的 write()
方法将引发 TypeError
。将一个 bytes
对象传递给文本流的 write()
方法也会引发 TypeError
。
文本 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
对象。不执行编码、解码或换行符转换。这类流可用于各种非文本数据,也可用于需要手动控制文本数据处理的情况。
创建二进制流最简单的方法是在模式字符串中使用带有 'b'
的 open()
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
。
如果你提供的 API 使用 open()
或 TextIOWrapper
并传递 encoding=None
作为参数,则可以使用 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()
的别名。此函数会使用参数 path、mode 和 flags 引发 审计事件
open
。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”。
- 异常 io.BlockingIOError¶
这是内置异常
BlockingIOError
的兼容性别名。
- 异常 io.UnsupportedOperation¶
当在流上调用不受支持的操作时,会引发继承自
OSError
和ValueError
的异常。
另请参阅
sys
包含标准 IO 流:
sys.stdin
、sys.stdout
和sys.stderr
。
类层次结构¶
I/O 流的实现被组织为一个类层次结构。首先是 抽象基类 (ABC),用于指定各种类别的流,然后是提供标准流实现的具体类。
注意
抽象基类还提供了一些方法的默认实现,以帮助实现具体的流类。例如,BufferedIOBase
提供了 readinto()
和 readline()
的未优化实现。
在 I/O 层次结构的顶部是抽象基类 IOBase
。它定义了流的基本接口。但是请注意,读取和写入流之间没有分隔;如果实现不支持给定的操作,则允许它们引发 UnsupportedOperation
。
RawIOBase
抽象基类继承自 IOBase
。它处理字节流的读写操作。 FileIO
是 RawIOBase
的子类,用于提供访问机器文件系统中文件的接口。
BufferedIOBase
抽象基类继承自 IOBase
。它处理原始二进制流 (RawIOBase
) 的缓冲。它的子类 BufferedWriter
、BufferedReader
和 BufferedRWPair
分别缓冲可写、可读以及可读可写的原始二进制流。 BufferedRandom
为可查找流提供了一个缓冲接口。另一个 BufferedIOBase
子类 BytesIO
是一个内存字节流。
TextIOBase
抽象基类继承自 IOBase
。它处理字节表示文本的流,并处理字符串的编码和解码。 TextIOWrapper
继承自 TextIOBase
,它是一个用于缓冲原始流 (BufferedIOBase
) 的缓冲文本接口。最后,StringIO
是一个用于文本的内存流。
参数名称不是规范的一部分,只有 open()
的参数才可以用作关键字参数。
下表总结了 io
模块提供的抽象基类
抽象基类 |
继承 |
存根方法 |
混合方法和属性 |
---|---|---|---|
|
|
||
|
继承自 |
||
|
继承自 |
||
|
继承自 |
I/O 基类¶
- class io.IOBase¶
所有 I/O 类的抽象基类。
此类为许多方法提供了空的抽象实现,派生类可以选择性地覆盖这些方法;默认实现表示无法读取、写入或查找的文件。
即使
IOBase
没有声明read()
或write()
,因为它们的签名会有所不同,但实现和客户端应该将这些方法视为接口的一部分。此外,当调用实现不支持的操作时,实现可能会引发ValueError
(或UnsupportedOperation
)。从文件读取或写入文件的二进制数据的基本类型是
bytes
。其他 类字节对象 也被接受作为方法参数。文本 I/O 类使用str
数据。请注意,在已关闭的流上调用任何方法(甚至是查询)都是未定义的。在这种情况下,实现可能会引发
ValueError
。IOBase
(及其子类)支持迭代器协议,这意味着可以迭代IOBase
对象,从而产生流中的行。行的定义略有不同,具体取决于流是二进制流(产生字节)还是文本流(产生字符串)。请参阅下面的readline()
。IOBase
也是一个上下文管理器,因此支持with
语句。在本例中,即使发生异常,*file* 也会在with
语句的代码块完成后关闭。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*,该偏移量相对于 *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, /)¶
将字节读入预先分配的可写 类字节对象 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 对象关闭时,该 fd 也将关闭,除非 closefd 设置为False
。
mode 可以是
'r'
、'w'
、'x'
或'a'
,分别用于读取(默认)、写入、独占创建或追加。如果在打开文件进行写入或追加时文件不存在,则将创建该文件;如果在打开文件进行写入时文件已存在,则将截断该文件。如果在打开文件进行创建时文件已存在,则将引发FileExistsError
。打开文件进行创建意味着写入,因此此模式的行为与'w'
类似。在模式中添加'+'
以允许同时进行读取和写入。此类上的
read()
(当使用正参数调用时)、readinto()
和write()
方法只会进行一次系统调用。可以通过传递可调用对象作为 opener 来使用自定义打开器。然后,通过使用 (name, flags) 调用 opener 来获取文件对象的底层文件描述符。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 是一个包含初始数据的 类字节对象。
除了
BufferedIOBase
和IOBase
中的方法外,BytesIO
还提供或重写了以下方法- 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
。除了
BufferedIOBase
和IOBase
中的方法外,BufferedReader
还提供或重写了以下方法- 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
对象被关闭或销毁时。
构造函数为给定的可写 raw 流创建一个
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
:“查找”到当前位置;*offset* 必须为零,这是一个无操作(不支持所有其他值)。SEEK_END
或2
:查找流的结尾;*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()
函数。