16.2. io
- 使用流的核心工具¶
源代码: Lib / io.py
16.2.1. Overview¶
io
模块提供了Python处理各种类型I / O的主要工具。有三种主要类型的I / O:文本I / O,二进制I / O和原始I / O。这些是通用类别,并且可以为它们中的每一个使用各种后备存储。属于这些类别中的任何一个的具体对象称为file object。其他常见术语是流和文件状对象。
独立于其类别,每个具体的流对象也将具有各种能力:它可以是只读的,只写的或读写的。它还可以允许任意随机存取(寻找向前或向后到任何位置),或只允许顺序存取(例如在套接字或管道的情况下)。
所有流都仔细考虑您给他们的数据类型。例如,给二进制流的str
对象write()
方法将引入TypeError
。因此,将向文本流的write()
方法提供bytes
对象。
16.2.1.1. Text I/O¶
文本I / O期望并生成str
对象。这意味着每当后台存储器本身由字节(例如在文件的情况下)时,数据的编码和解码被透明地以及平台特定的换行字符的可选转换。
创建文本流的最简单方法是使用open()
,可选择指定编码:
f = open("myfile.txt", "r", encoding="utf-8")
内存中的文本流也可用作StringIO
对象:
f = io.StringIO("some initial text data")
文本流API在TextIOBase
的文档中有详细描述。
16.2.1.2. 二进制I / O ¶
二进制I / O(也称为缓冲I / O)期望字节状对象并产生字节
对象。不执行编码,解码或换行。这种类别的流可以用于所有种类的非文本数据,并且当需要对文本数据的处理的手动控制时。
创建二进制流的最简单方法是在模式字符串中使用open()
和'b'
f = open("myfile.jpg", "rb")
内存中的二进制流也可用作BytesIO
对象:
f = io.BytesIO(b"some initial binary data: \x00\x01")
二进制流API在BufferedIOBase
的文档中有详细描述。
其他库模块可以提供用于创建文本或二进制流的附加方式。例如,请参见socket.socket.makefile()
。
16.2.2. High-level Module Interface¶
-
io.
open
(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)¶ 这是内置
open()
函数的别名。
- exception
io.
BlockingIOError
¶ 这是内置
BlockingIOError
异常的兼容性别名。
- exception
io.
UnsupportedOperation
¶ 在流上调用不受支持的操作时引发的异常继承
OSError
和ValueError
。
16.2.2.1. In-memory streams¶
也可以使用str
或bytes-like object作为读和写的文件。对于字符串StringIO
可以像在文本模式下打开的文件一样使用。BytesIO
可以像在二进制模式下打开的文件一样使用。两者都提供了随机存取的完全读写能力。
也可以看看
sys
- 包含标准IO流:
sys.stdin
,sys.stdout
和sys.stderr
。
16.2.3. Class hierarchy¶
I / O流的实现被组织为类的层次结构。第一个abstract base classes(ABCs),用于指定流的各种类别,然后是提供标准流实现的具体类。
Note
The abstract base classes also provide default implementations of some methods in order to help implementation of concrete stream classes. For example,
BufferedIOBase
provides unoptimized implementations ofreadinto()
andreadline()
.
在I / O层次结构的顶部是抽象基类IOBase
。它定义了流的基本接口。但是,请注意,读取和写入流之间没有分离;如果实现不支持给定的操作,则允许引用UnsupportedOperation
。
RawIOBase
ABC延伸IOBase
。它处理字节读取和写入流。FileIO
子类RawIOBase
为机器文件系统中的文件提供接口。
BufferedIOBase
ABC处理原始字节流(RawIOBase
)上的缓冲。其子类,可读,可写,可读可写的BufferedWriter
,BufferedReader
和BufferedRWPair
BufferedRandom
为随机存取流提供缓冲接口。另一个BufferedIOBase
子类,BytesIO
是一个内存中字节流。
TextIOBase
ABC是IOBase
的另一个子类,它处理字节代表文本的流,并处理字符串的编码和解码。TextIOWrapper
(扩展它)是缓冲的原始流的缓冲文本接口(BufferedIOBase
)。最后,StringIO
是文本的内存流。
参数名称不是规范的一部分,只有open()
的参数用作关键字参数。
下表总结了由io
模块提供的ABC:
ABC | 继承 | 存根方法 | Mixin方法和属性 |
---|---|---|---|
IOBase | fileno ,seek 和truncate | close , closed , __enter__ , __exit__ , flush , isatty , __iter__ , __next__ , readable , readline , readlines , seekable , tell , writable , and writelines | |
RawIOBase | IOBase | readinto 和write | 继承IOBase 方法,read 和readall |
BufferedIOBase | IOBase | detach ,read ,read1 和write | 继承IOBase 方法,readinto |
TextIOBase | IOBase | detach ,read ,readline 和write | 继承了IOBase 方法,encoding ,errors 和newlines |
16.2.3.1. I/O Base Classes¶
- class
io.
IOBase
¶ 所有I / O类的抽象基类,作用于字节流。没有公共构造函数。
这个类为许多方法提供了空的抽象实现,派生类可以有选择地重写;默认实现表示不能读取,写入或查找的文件。
即使
IOBase
未声明read()
,readinto()
或write()
此外,当调用不支持的操作时,实现可以引入ValueError
(或UnsupportedOperation
)。用于从文件读取或写入文件的二进制数据的基本类型为
bytes
。其他bytes-like objects也被接受为方法参数。在某些情况下,例如readinto()
,需要可写对象(例如bytearray
)。文本I / O类使用str
数据。请注意,在封闭流上调用任何方法(甚至查询)都是未定义的。在这种情况下,实现可能会引发
ValueError
。IOBase
(及其子类)支持迭代器协议,这意味着可以迭代一个IOBase
对象,以生成流中的行。根据流是二进制流(产生字节)还是文本流(产生字符串),行定义稍有不同。请参阅下面的readline()
。IOBase
也是一个上下文管理器,因此支持with
语句。在此示例中,文件在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()
的换行符参数可用于选择识别的行终止符。
-
readlines
(hint=-1)¶ 读取并返回流中的行列表。可以指定提示以控制读取的行数:如果所有行的总大小(以字节/字符)超过hint,则不会再读取行。
Note that it’s already possible to iterate on file objects using
for line in file: ...
without callingfile.readlines()
.
-
seek
(offset[, whence])¶ 将流位置更改为给定字节偏移量。偏移相对于由whence指示的位置进行解释。whence的默认值为
SEEK_SET
。whence的值为:SEEK_SET
或0
- 流的开始(默认); offset应为零或正数SEEK_CUR
或1
- 当前流位置; offset可能为负值SEEK_END
或2
- 流的结束; offset通常为负数
返回新的绝对位置。
版本3.1中的新功能:
SEEK_*
常数。版本3.3中的新功能:某些操作系统可能支持其他值,例如
os.SEEK_HOLE
或os.SEEK_DATA
。文件的有效值可能取决于它是以文本还是二进制模式打开。
-
seekable
()¶ 如果流支持随机访问,则返回
True
。IfFalse
,seek()
,tell()
andtruncate()
will raiseOSError
.
-
tell
()¶ 返回当前流位置。
-
truncate
(size=None)¶ 将流大小调整为给定的大小(如果未指定大小,则为当前位置)。当前流位置不更改。此调整大小可以扩展或减小当前文件大小。在扩展的情况下,新文件区域的内容取决于平台(在大多数系统上,附加字节为零填充)。返回新文件大小。
在3.5版本中已更改: Windows将在扩展时将零填充文件。
-
writable
()¶ 如果流支持写入,则返回
True
。如果False
,write()
和truncate()
将引发OSError
。
-
writelines
(lines)¶ 向流中写入一行列表。不添加行分隔符,因此通常为每个提供的行在末尾具有行分隔符。
-
- class
io.
RawIOBase
¶ 原始二进制I / O的基类。它继承
IOBase
。没有公共构造函数。原始二进制I / O通常提供对底层操作系统设备或API的低级访问,并且不尝试将其封装在高级原语中(这留给缓冲I / O和文本I / O,将在本文后面描述页)。
除了来自
IOBase
的属性和方法,RawIOBase
提供以下方法:-
read
(size=-1)¶ 从对象中读取size字节并返回它们。为方便起见,如果size未指定或-1,则调用
readall()
。否则,只有一个系统调用。如果操作系统调用返回的小于大小字节,则可能会返回小于大小的字节。如果返回0字节,并且size不为0,则表示文件结束。如果对象处于非阻塞模式并且没有字节可用,则返回
None
。
-
readall
()¶ 读取并返回流中的所有字节,直到EOF,如果必要,使用多个调用流。
-
readinto
(b)¶ 将字节读入预分配的可写入bytes-like object b,并返回读取的字节数。如果对象处于非阻塞模式并且没有字节可用,则返回
None
。
-
write
(b)¶ 将给定的bytes-like object,b写入基础原始流,并返回写入的字节数。这可以小于以字节为单位的b的长度,这取决于基本原始流的细节,特别是如果它处于非阻塞模式。如果原始流设置为不阻塞,并且没有单个字节可以轻松写入,则返回
None
。在此方法返回后,调用者可以释放或改变b,因此实现应该只在方法调用期间访问b。
-
- 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)¶ 读取并返回大小大小字节。如果省略参数,则
None
或负数,读取并返回数据,直到到达EOF。如果流已经处于EOF,则返回一个空的bytes
对象。如果参数是正的,并且基本的原始流不是交互式的,则可以发出多个原始读取以满足字节计数(除非首先达到EOF)。但是对于交互式原始流,最多只会发出一次原始读取,而较短的结果并不意味着EOF即将来临。
如果基础原始流处于非阻塞模式,并且此时没有可用数据,则会引发
BlockingIOError
。
-
read1
(size=-1)¶ 读取并返回最多size字节,最多只能调用基础原始流的
read()
(或readinto()
)方法。如果您在BufferedIOBase
对象的顶部实现自己的缓冲,这可能很有用。
-
readinto
(b)¶ 将字节读入预分配的可写入bytes-like object b并返回读取的字节数。
像
read()
,可以向底层原始流发出多个读取,除非后者是交互式的。如果基础原始流处于非阻塞模式,并且此时没有可用数据,则会引发
BlockingIOError
。
-
readinto1
(b)¶ Read bytes into a pre-allocated, writable bytes-like object b, using at most one call to the underlying raw stream’s
read()
(orreadinto()
) method. 返回读取的字节数。如果基础原始流处于非阻塞模式,并且此时没有可用数据,则会引发
BlockingIOError
。版本3.5中的新功能。
-
write
(b)¶ 写入给定的bytes-like object,b,并返回写入的字节数(总是等于b如果写操作失败,则会出现
OSError
)。根据实际实现,这些字节可以容易地写入底层流,或者由于性能和等待时间的原因保持在缓冲器中。当处于非阻塞模式时,如果数据需要写入原始流,但不能接受所有数据而不阻塞,则会引发
BlockingIOError
。在此方法返回后,调用者可以释放或改变b,因此实现应该只在方法调用期间访问b。
-
16.2.3.2. Raw File I/O¶
- class
io.
FileIO
(name, mode='r', closefd=True, opener=None)¶ FileIO
表示包含字节数据的操作系统级文件。它实现RawIOBase
接口(因此也实现IOBase
接口)。名称可以是以下两种情况之一:
- 一个字符串或
bytes
对象,表示要打开的文件的路径。在这种情况下,closefd必须为True(默认值),否则会引发错误。 - 一个表示现有OS级别文件的编号的整数,由此产生的
FileIO
对象将赋予访问权限。当FileIO对象关闭时,fd也将关闭,除非closefd设置为False
。
The mode can be
'r'
,'w'
,'x'
or'a'
for reading (default), writing, exclusive creation or appending. 该文件将被创建,如果它不存在时打开进行写或附加;它会在打开时被截断。FileExistsError
将会被提出,如果它在打开时已经存在。打开用于创建的文件意味着写入,因此此模式的行为方式类似于'w'
。将'+'
添加到模式以允许同时读取和写入。read()
(当使用正参数调用时),此类的readinto()
和write()
通过传递可调用对象opener可以使用自定义开启器。然后通过使用(名称,标志)调用opener获得文件对象的基础文件描述器。opener must return an open file descriptor (passing
os.open
as opener results in functionality similar to passingNone
).新创建的文件为non-inheritable。
有关使用开启参数的示例,请参见
open()
内建函数。在版本3.3中已更改:添加了开启程序参数。添加了
'x'
模式。在版本3.4中更改:此文件现在是不可继承的。
除了
IOBase
和RawIOBase
的属性和方法,FileIO
提供以下数据属性:-
mode
¶ 在构造函数中给出的模式。
-
name
¶ 文件名。这是当在构造函数中没有给出名称时文件的描述器。
- 一个字符串或
16.2.3.3. 缓冲流 ¶
缓冲I / O流为I / O设备提供了比原始I / O更高级别的接口。
- class
io.
BytesIO
([initial_bytes])¶ 使用内存中字节缓冲区的流实现。它继承
BufferedIOBase
。当调用close()
方法时,缓冲区将被丢弃。可选参数initial_bytes是包含初始数据的bytes-like object。
除了来自
BufferedIOBase
和IOBase
的BytesIO
提供或覆盖这些方法:
- 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])¶ 从流中返回字节,但不推进位置。对原始流最多只能进行一次读取以满足调用。返回的字节数可以小于或大于请求的字节数。
-
read
([size])¶ 读取并返回大小字节,或者如果大小没有给出或为负,直到EOF或读取调用在非阻塞模式下阻塞。
-
read1
(size)¶ 读取并返回最多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)¶ 写入bytes-like object,b,并返回写入的字节数。当处于非阻塞模式时,如果缓冲区需要被写出而原始流被阻塞,则会引发
BlockingIOError
。
- class
io.
BufferedRandom
(raw, buffer_size=DEFAULT_BUFFER_SIZE)¶ 缓冲接口,用于随机访问流。它继承
BufferedReader
和BufferedWriter
,并进一步支持seek()
和tell()
功能。构造函数为第一个参数中给出的可寻找的原始流创建一个读取器和写入器。如果省略buffer_size,它默认为
DEFAULT_BUFFER_SIZE
。
- class
io.
BufferedRWPair
(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE)¶ 缓冲I / O对象将两个单向
RawIOBase
对象(一个可读,另一个可写)组合到单个双向端点中。它继承BufferedIOBase
。读取器和写入器是分别可读和可写的
RawIOBase
对象。如果省略buffer_size,它默认为DEFAULT_BUFFER_SIZE
。BufferedRWPair
实施除了detach()
之外的所有BufferedIOBase
方法,其引发UnsupportedOperation
。警告
BufferedRWPair
不会尝试同步对其基础原始流的访问。你不应该把它作为读者和作家的同一个对象;请改用BufferedRandom
。
16.2.3.4. 文本 I/O ¶
- class
io.
TextIOBase
¶ 文本流的的基类。此类提供一个字符和网格线的基于的界面流 i/o。这里没有
readinto()
的方法,因为 Python 的字符串是不可变的。它继承了IOBase
。这里没有公共构造函数。TextIOBase
提供或重写这些数据的属性和方法除了那些从IOBase
:-
encoding
¶ 用来解码流的字节转换为字符串,并将字符串编码为字节编码的名称。
-
errors
¶ 解码器或编码器的错误设置。
-
newlines
¶ 一个字符串,字符串,或
无
指示换行符的元组翻译到目前为止。根据实现和初始构造函数标志,这可能不可用。
-
buffer
¶ TextIOBase
处理的基本二进制缓冲区(BufferedIOBase
实例)。这不是TextIOBase
API的一部分,在某些实现中可能不存在。
-
detach
()¶ 将底层的二进制缓冲区与
TextIOBase
分开并返回。分离下层缓冲区后,
TextIOBase
处于不可用状态。一些
TextIOBase
实现,如StringIO
,可能没有底层缓冲区的概念,并调用此方法将引发UnsupportedOperation
。版本3.1中的新功能。
-
readline
(size=-1)¶ 读取直到换行符或EOF并返回单个
str
。如果流已经在EOF,则返回一个空字符串。如果指定size,则最多只能读取size个字符。
-
seek
(offset[, whence])¶ 将流位置更改为给定的偏移。行为取决于whence参数。whence的默认值为
SEEK_SET
。SEEK_SET
或0
:从流的开始寻找(默认); offset必须是由TextIOBase.tell()
返回的数字,或零。任何其他偏移值会产生未定义的行为。SEEK_CUR
或1
:“seek”到当前位置; 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.getpreferredencoding(False)
。errors是一个可选字符串,用于指定如何处理编码和解码错误。Pass
'strict'
to raise aValueError
exception if there is an encoding error (the default ofNone
has the same effect), or pass'ignore'
to ignore errors. (请注意,忽略编码错误可能会导致数据丢失。)'replace'
会导致替换标记(例如'?'
)插入到存在格式错误的数据的位置。'backslashreplace'
导致格式错误的数据被反斜杠转义序列替换。写入时,'xmlcharrefreplace'
(替换为相应的XML字符引用)或'namereplace'
(替换为\N{...}
已使用codecs.register_error()
注册的任何其他错误处理名称也有效。换行符控制如何处理行尾。It can be
None
,''
,'\n'
,'\r'
, and'\r\n'
. 它的工作原理如下:- 从流读取输入时,如果换行符为
None
,则启用universal newlines模式。输入中的行可以以'\n'
,'\r'
或'\r\n'
结尾,在'\n'
中,然后返回给调用者。如果它是''
,则启用通用换行符模式,但行结尾将返回给未转换的调用者。如果它具有任何其他合法值,则输入行仅由给定字符串终止,并且行结尾被返回给未经翻译的调用者。 - When writing output to the stream, if newline is
None
, any'\n'
characters written are translated to the system default line separator,os.linesep
. 如果换行符是''
或'\n'
,则不会进行转换。如果换行符是任何其他合法值,写入的任何'\n'
字符都将转换为给定字符串。
如果line_buffering是
True
,则当写入调用包含换行符时,将隐含flush()
。If write_through is
True
, calls towrite()
are guaranteed not to be buffered: any data written on theTextIOWrapper
object is immediately handled to its underlying binary buffer.在版本3.3中已更改:已添加write_through参数。
在版本3.3中更改:默认的编码现在为
locale.getpreferredencoding(False)
,而不是locale.getpreferredencoding()
请勿使用locale.setlocale()
临时更改语言区域编码,而是使用当前语言环境编码,而不是用户首选编码。TextIOWrapper
除了TextIOBase
及其父项提供一个属性:-
line_buffering
¶ 是否启用线路缓冲。
- 从流读取输入时,如果换行符为
- class
io.
StringIO
(initial_value='', newline='\n')¶ 用于文本I / O的内存中流。当调用
close()
方法时,文本缓冲区将被丢弃。可以通过提供initial_value来设置缓冲区的初始值。如果启用了换行符,则换行符将按照
write()
进行编码。流位于缓冲区的开始。换行符参数的工作方式类似于
TextIOWrapper
。默认设置仅将\n
字符视为行的末尾,并且不进行换行。如果换行符设置为None
,则在所有平台上将换行符写为\n
,但是读取时仍会执行通用换行符解码。StringIO
除了来自TextIOBase
及其父类的方法,还提供此方法:用法示例:
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
。
16.2.4. Performance¶
本节讨论提供的具体I / O实现的性能。
16.2.4.1. Binary I/O¶
通过只读取和写入大量数据,即使用户请求单个字节,缓冲I / O隐藏了调用和执行操作系统的未缓冲I / O例程的任何低效率。增益取决于OS和执行的I / O的种类。例如,在某些现代操作系统(如Linux)上,无缓冲磁盘I / O可以与缓冲I / O一样快。然而,底线是缓冲I / O提供可预测的性能,而不管平台和后备设备。因此,对于二进制数据,几乎总是优选使用缓冲I / O而不是无缓冲I / O。
16.2.4.2. Text I/O¶
二进制存储(例如文件)上的文本I / O比同一存储上的二进制I / O慢得多,因为它需要使用字符编解码器在Unicode和二进制数据之间进行转换。这可以变得明显处理大量的文本数据,如大日志文件。此外,由于使用重构算法,TextIOWrapper.tell()
和TextIOWrapper.seek()
都相当慢。
16.2.4.3. Multi-threading¶
FileIO
对象在操作系统调用(例如Unix下的read(2)
)范围内是线程安全的,它们也是线程安全的。
二进制缓冲对象(BufferedReader
,BufferedWriter
,BufferedRandom
和BufferedRWPair
)的实例使用锁保护其内部结构;因此可以安全地同时从多个线程调用它们。
TextIOWrapper
对象不是线程安全的。
16.2.4.4. Reentrancy¶
二进制缓冲对象(BufferedReader
,BufferedWriter
,BufferedRandom
和BufferedRWPair
)的实例不可重入。虽然在正常情况下不会发生可重入呼叫,但它们可能来自在signal
处理程序中执行I / O。如果线程尝试重新输入它已经访问的缓冲对象,则会引发RuntimeError
。注意,这并不禁止不同的线程进入缓冲对象。
上面隐含地扩展到文本文件,因为open()
函数会将缓冲对象包裹在TextIOWrapper
内。这包括标准流,因此也影响内建函数print()
。