概述

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

高级模块接口的文档中详细描述

io.DEFAULT_BUFFER_SIZE
一个int,包含模块缓冲的I / Oclasses使用的默认缓冲区大小。open()如果可能的话,使用文件的blksize(由os.stat()获得)
io.open (文件mode=\”r\”缓冲= -1 编码=无错误=无换行符=无 closefd =真 opener =无
这是内置的一个别名open() function.
exception io.BlockingIOError
这是一个兼容性别名for builtin BlockingIOErrorexception.
exception io.UnsupportedOperation
继承OSErrorValueError的异常,当一个不受支持的操作被调用时会被引发stream.

Inmemeory streams

也可以使用str字节对象作为读取和写入的文件。对于字符串StringIO可以像在文本模式下打开的文件一样使用。BytesIO可以像二进制模式下打开的文件一样使用。两者都提供randomaccess的完全读写功能。

另见

sys
包含标准IO流:sys.stdinsys.stdoutsys.stderr

类层次

I / O流的实现被组织为类的层次结构。首先抽象基类(ABCs),用于指定各种类型的流,然后是提供标准流实现的具体类。

注意

抽象基类还提供了一些方法的默认实现,以帮助实现具体的流类。例如,BufferedIOBase提供了readinto()readline()

的未经优化的实现
在I / O层次结构的顶部是抽象基类IOBase。它定义了流的基本接口。但请注意,读取和写入流之间存在分离;如果它们不支持给定的操作,则允许实现UnsupportedOperation

RawIOBase ABC扩展IOBase。它处理读取和写入流的字节。FileIO子类RawIOBase为机器文件系统中的文件提供接口。

BufferedIOBaseABC处理原始字节流(RawIOBase)上的缓冲。它的子类BufferedWriterBufferedReaderBufferedRWPair缓冲流是可读的,可写的,并且是可读写的。BufferedRandom为随机访问流提供缓冲接口。另一个BufferedIOBase子类BytesIO是一个内存中的流。

TextIOBase ABC是IOBase的另一个子类,它处理其字节代表文本的流,并处理字符串的编码和解码。TextIOWrapper,扩展它,是缓冲原始流(BufferedIOBase)的缓冲文本接口。最后,StringIO是文本的内存流。

参数名称不是规范的一部分,只有open()的参数用作关键字参数。

下表总结了io模块提供的ABC:

ABC 继承 存根方法 Mixin方法和属性
IOBase filenoseek,和truncate closeclosed__enter____exit__flushisatty__iter____next__readablereadlinereadlinesseekabletellwritable,和writelines
RawIOBase IOBase readintowrite 继承IOBase方法,readreadall
BufferedIOBase IOBase detachreadread1,和write 继承IOBase方法,readinto,和readinto1
TextIOBase IOBase detachreadreadline,和write 继承IOBase方法,encodingerrorsnewlines

I / O基类

class io.IOBase
所有I / O类的抽象基类,作用于字节流。没有公共构造函数。

此类为许多方法提供空抽象实现,派生类可以有选择地覆盖;defaultimplementations表示无法读取,写入orseeked的文件。

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

用于从文件读取或写入文件的二进制数据的基本类型是bytes。其他类似字节的对象也被接受为方法参数。在某些情况下,例如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如果流关闭了
fileno//(
如果是itexists,则返回流的基础文件描述符(整数)。如果IO对象不使用filedescriptor OSError
flush)如果适用,则刷新流的写缓冲区,引发
。这对于只读和非阻塞流没有任何作用.
isatty ()
如果流是交互式的(或连接到终端),则返回True/ tty device).
readable
返回True如果可以读取流。如果Falseread()将提升OSError
readline size = -1
从流中读取并返回一行。如果指定大小,则将读取大小字节。

对于二进制文件,行终止符总是b"\n";对于文本文件,换行open()的参数可用于选择识别的行终止符.

readlines提示= -1
从流中读取并返回行列表。暗示可以指定控制读取的行数:如果到目前为止所有行的总大小(以字节/字符为单位)超过提示

请注意,已经可以使用forline in file: ...迭代文件对象而无需调用file.readlines()

seek偏移 [ whence ]
将流位置改为给定的字节offset offset 相对于 whence 指示的位置进行解释。的默认值SEEK_SET的值是:

  • SEEK_SET 要么 0– 开始流(默认); 偏移应为零或正
  • SEEK_CUR1 – 当前流位置;偏移可能是否定的
  • SEEK_END2 – 流的结尾;偏移通常是负的

返回新的绝对位置。

版本3.1中新增: SEEK_*常量。

版本3.3中的新内容:某些操作系统可以支持其他值,例如os.SEEK_HOLEos.SEEK_DATA。文件的有效值可能取决于它是以文本还是二进制模式打开。

seekable
返回True如果流支持随机访问。如果Falseseek()tell()truncate()会抬起OSError
tell
返回当前的流位置
truncate//( size =无
将流调整为给定的大小以字节为单位(或当前位置大小未指定)。当前流位置未更改。此大小调整可以扩展或减小当前文件大小。在扩展的情况下,新文件区域的内容取决于平台(在大多数系统上,额外的字节是零填充的)。返回新文件大小

更改版本3.5: Windows现在将在扩展时归零文件。

writable
返回True如果流支持写入。如果Falsewrite()truncate()会举起OSError
writelines
写一个行列表到流。不添加行分隔符,因此通常每条行提供的行都有一个行分隔符
__del__// ()
准备破坏对象。IOBase提供了这个方法的defaultimplementation,它调用实例的close()方法
class io.RawIOBase
原始二进制I / O的基类。它继承了IOBase。有一个nopublic构造函数。

原始二进制I / O通常提供对底层OS设备或API的低级访问,并且不会尝试将其封装在高级原语中(这留给缓冲I / O和文本I / O,本页稍后将对此进行介绍))。

除了IOBaseRawIOBase的属性和方法之外,还提供了以下方法:

read size = -1
从对象读取大小字节并归还他们。为方便起见,如果大小未指定或-1,则返回EOF之前的所有字节。否则,只进行一次系统调用。小于尺寸如果操作系统调用返回少于大小字节,则可能返回字节。

如果返回0个字节,并且大小不为0,则表示文件结束。如果对象处于非阻塞模式且没有可用的字节,则None被退回。

默认实现推迟到readall()readinto()

readall
读取并返回流中的所有字节,直到EOF,如果使用multiplecalls到流必要的
readinto (b)
将字节读入预先分配的,可写的字节对象 b ,并返回读取的字节数。如果对象处于非阻塞模式且没有可用的字节,则None返回.
write (b)
将给定的字节对象 b 写入下面的原始流,并返回写入的字节数。这可能小于 b inbytes的长度,具体取决于底层原始流的具体情况,特别是如果它处于非阻塞模式。None如果原始流设置为不阻塞并且没有单个字节可以容易地写入它,则返回。调用者可以在此方法返回后释放或改变 b ,因此实现只能在方法调用期间访问 b
class io.BufferedIOBase
支持某种缓冲的二进制流的基类。它继承IOBase。没有公共构造函数。

RawIOBase的主要区别在于方法read()readinto()write()将尝试(分别)读取所请求的输入量或消耗所有给定的输出,但代价可能是更多比一个系统调用。

另外,如果底层原始流处于非阻塞模式并且不能获取或提供足够的数据,那些方法可以提升BlockingIOError;不像他们的RawIOBase同行,他们什么时候会回来None

此外,read()方法没有一个违反readinto()的defaultimplementation。

一个典型的BufferedIOBase实现不应该继承RawIOBase实现,但包装一个,如BufferedWriterBufferedReader做。

BufferedIOBase提供或覆盖这些方法和属性,而不是来自IOBase

raw
RawIOBase处理的基础原始流(BufferedIOBase实例)。这不是BufferedIOBase API的一部分,在某些实现中可能不存在.
detach ()
从缓冲区中分离出底层原始流把它返还。

原始流分离后,缓冲区处于不可用状态。

某些缓冲区(如BytesIO)没有从此方法返回单一流的概念。他们举起UnsupportedOperation

新版3.1.
read (size=-1)
阅读并返回大小字节。如果省略参数,None或负数,则读取并返回数据,直到达到EOF。空bytes如果流已经在EOF,则返回对象。

如果参数为正,并且基础原始流不是交互式的,则可以发出多个原始读取以满足字节计数(除非首先达到EOF)。但对于交互式原始流,最多只会发出一次原始读取,而简短的结果并不意味着EOF是非常重要的。

如果底层原始流是无限阻塞模式,并且目前没有可用数据,则会引发BlockingIOError.

read1( [size]
读取并返回大小字节,最多只调用一次原始流的read()(或readinto())方法。如果您在BufferedIOBase对象上实现自己的缓冲,这可能很有用。

如果大小-1(默认值),则返回任意数量的字节(除非达到EOF,否则大于零).

readinto b
将字节读入预先分配的,可写的字节对象 b 并返回读取的字节数。

read()一样,可以向底层原始流发出多个读取,除非后者是交互式的。

如果基础原始流处于非阻塞模式,并且此时没有可用数据,则会引发BlockingIOError.

readinto1(b
将字节读入预分配的,可写的字节对象 b ,最多使用一次调用底层原始流read()(或readinto())方法返回读取的字节数。

如果基础原始流处于非阻塞模式,并且此时没有可用数据,则会引发BlockingIOError

版本3.5中的新内容
write// (b)
用给定的字节来写对象 b ,并返回写入的字节数(总是等于 b 的长度,以字节为单位,因为如果写入失败OSError将被提出)。根据实际实现,这些字节可以很容易地写入底层流,或者保存在缓冲区中以获得性能和延迟原因。

当处于非阻塞模式时,如果需要将数据写入原始流但是它无法接受所有数据而没有阻塞,则会引发BlockingIOError

调用者可以在此方法返回后释放或改变 b ,因此实现只应在方法调用期间访问 b

原始文件I / O

io.FileIO名称 mode =“r” closefd = True opener =无
FileIO表示包含字节数据的操作系统级文件。它实现了RawIOBase接口(因此IOBase接口也是如此)。

名称可以是以下两种情况之一:

  • 一个字符串或bytes对象,表示将要打开的文件的路径。在这种情况下,closefd必须是True(默认值),否则会出错.
  • 一个整数,表示生成的FileIO对象将提供访问权限的现有操作系统级文件描述符的编号。当关闭文件对象时,这个fd也将被关闭,除非 closefd 设置为False

模式可以是"r""w""x""a"用于阅读(默认),写作,独家创作或追加。如果在打开写入或附加时该文件不存在,则该文件将被处理;它会在打开写入时被截断。如果打开创建时已经存在FileExistsError将被提升。打开文件以创建简单的写入,因此该模式的行为方式与"w"类似。在模式中添加"+"以允许同时读写。

read()(用正面参数调用时),readinto()write()这个类的方法只会进行一次系统调用。

可以通过传递一个可调用的开启者来使用自定义开启器。然后通过调用开启者带(名称标志)。开启者必须返回一个打开的文件描述符(传递os.open开启者导致功能类似于传递None)。

新创建的文件不可继承

有关使用open()开启参数的示例,请参阅内置函数。

在版本3.3中更改:添加了开启参数。添加了"x"模式。

在版本3.4中更改:文件现在是不可继承的。

除了IOBaseRawIOBaseFileIO的属性和方法之外,还提供了以下数据属性:

mode
构造函数中给出的模式.
name
文件名。当构造函数中没有名称时,这是文件的文件描述符.

Buffered Streams

缓冲I / O流为原始I / O提供了更高级别的I / O接口。

class io.BytesIO [ initial_bytes ]
使用内存中字节缓冲区的流实现。它继承了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 ( [尺寸]
BytesIO,这跟read()

更改版本3.7:尺寸参数现在是可选的。

readinto1b
BytesIO,这与readinto()

版本3.5相同。
class io.BufferedReader raw buffer_size = DEFAULT_BUFFER_SIZE
一个缓冲区,提供对可读,顺序RawIOBase对象的更高级别访问。它继承BufferedIOBase。当从该对象读取数据时,可以从底层原始流请求更大量的数据,并将其保存在内部缓冲区中。然后可以在后续读取时直接返回缓冲的数据。

构造函数为给定的可读BufferedReader raw stream和 buffer_size 创建一个。如果省略 buffer_size ,则使用DEFAULT_BUFFER_SIZE

BufferedReader除了BufferedIOBaseIOBase之外,还提供或覆盖了这些方法:

peek [ size ]
从流中返回字节而不提升位置。最多单个读取原始流以完成呼叫。返回的字节数可能少于或多于要求.
read ( [size])
读取并返回大小字节,或者大小是给定还是否定,直到EOF或如果读取呼叫会以非阻塞模式阻止.
read1 ( [size]
读取并返回大小字节,只对原始流进行一次调用。如果至少缓冲一个字节,则只缓冲字节返回。否则,进行一次原始流读取调用。

在版本3.7中更改: 大小参数现在是可选的。

class io.BufferedWriter raw buffer_size = DEFAULT_BUFFER_SIZE
提供更高级访问权限的缓冲区到一个可写的,顺序的RawIOBase对象。它继承BufferedIOBase。写入此对象时,数据通常放入内部缓冲区。缓冲区将在各种条件下写出到底层RawIOBase对象,包括:

  • 当缓冲区对于所有待处理数据变得太小时;
  • flush()被调用时;
  • 当需要seek()时(对于BufferedRandom物品);
  • BufferedWriter物体被关闭或毁坏时

构造函数为给定的可写BufferedWriter原始流创建一个。如果没有给出 buffer_size ,则默认为DEFAULT_BUFFER_SIZEBufferedWriter提供或覆盖这些方法以及BufferedIOBaseIOBase

flush
将缓冲区中保存的字节强制转换为原始流。如果原始流阻塞,应该提高BlockingIOError
write (b)
bytes-like object b ,并返回写入的字节数。当处于非阻塞模式时,如果需要写出缓冲区,则会引发BlockingIOError但原始流阻塞
//class io.BufferedRandom raw buffer_size = DEFAULT_BUFFER_SIZE
随机访问流的缓冲接口。它继承了BufferedReaderBufferedWriter,并进一步支持seek()tell()功能。

构造函数为第一个参数中给出的可搜索原始流创建了一个读写器。如果 buffer_size 被省略,则默认为DEFAULT_BUFFER_SIZEBufferedRandom可以有任何BufferedReaderBufferedWriter可以做.

class io.BufferedRWPair读者作家 buffer_size = DEFAULT_BUFFER_SIZE
一个缓冲的I / O对象,将两个单向RawIOBase对象 – 一个可读,另一个可写 – 组合成一个双向终点。它继承BufferedIOBase读者编者分别是RawIOBase可读和可写的对象。如果省略 buffer_size ,则默认为DEFAULT_BUFFER_SIZEBufferedRWPair实现BufferedIOBase的所有方法,而不是detach(),这会引发UnsupportedOperation

警告

BufferedRWPair不会尝试同步访问基础原始流。你不应该把它和读者和作者一样传递给它;用BufferedRandom代替

文本I / O

io.TextIOBase
文本流的基类。此类为流I / O提供基于字符和行的接口。没有readinto()方法,因为Python的字符串是不可变的。它继承IOBase。没有公共构造函数。

TextIOBase提供或覆盖这些数据属性和IOBase以外的方法和方法:

encoding
用于解码流的字节intostrings并将字符串编码为字节的编码名称.
errors
解码器或编码器的错误设置.
newlines
字符串,字符串元组或None,表明到目前为止新线传输。根据实现和initialconstructor标志,这可能不可用.
buffer
底层二进制缓冲区(BufferedIOBase那个TextIOBase对付。这不是TextIOBaseAPI并且在某些实现中可能不存在.
detach
将底层二进制缓冲区与TextIOBase并且回复它。

在分离底层缓冲区后,TextIOBase处于不可用状态。

有些TextIOBase实现,比如StringIO,可能没有底层缓冲区的概念,调用这个方法会引发UnsupportedOperation

版本3.1.
readsize=-1
最多读取和返回大小流中的字符为单个str。如果尺寸为负或None,则读到EOF.
readline(size=-1
读取直到换行符或EOF并返回单个str。如果流已经在EOF,则返回空字符串。

如果指定尺寸,最多尺寸将被读取字符

seek (offset [ whence ]
将流的位置改为给定的偏移。行为取决于 whence 参数。的默认值SEEK_SET

  • SEEK_SET0:从流的开头搜索(默认值);偏移必须是TextIOBase.tell()返回的数字,或者为零。任何其他偏移 valueproduces undefined behaviour。
  • SEEK_CUR1:“寻找”到当前位置; 偏移必须为零,这是一个无操作(所有其他值都不受支持).
  • SEEK_END2:寻找到流的末尾; 偏移必须为零(所有其他值都不受支持).

将新的绝对位置作为不透明数字返回。

版本3.1中新增: SEEK_*常量。

tell
将当前流位置作为不透明数字返回。数字通常不代表底层二进制存储器中的字节数.
write (s)
写成字符串s 到流并返回写入的字符数.
class io.TextIOWrapper缓冲编码=无 errors =无 newline =无 line_buffering = False write_through = False
缓冲的文本流在BufferedIOBase二进制流上。它继承了TextIOBase编码给出了将被解码的流编码的名称。默认为locale.getpreferredencoding(False)错误是一个可选字符串,用于指定如何处理编码和解决错误。如果有编码错误(默认为"strict"),请ValueError提出None具有相同的效果),或通过"ignore"忽略错误。(请注意,忽略编码会导致数据丢失。)"replace"会导致替换标记(例如"?")插入格式错误的数据。"backslashreplace"导致格式错误的数据被abackslashed转义序列取代。在编写时,可以使用"xmlcharrefreplace"(用适当的XML字符引用替换)或"namereplace"(用\N{...}转义序列替换)。使用codecs.register_error()注册的任何其他错误处理名称也是有效的。

换行符控制行结尾的处理方式。它可以是None"""\n""\r""\r\n"。它的工作原理如下:

  • 当从流中读取输入时,如果换行None通用换行符模式已启用。输入中的行可以以"\n""\r""\r\n"结尾,并在返回给调用者之前将它们转换为"\n"。如果是 "",通用newlinesmode已启用,但行结尾将返回给调用者未翻译。如果它具有任何其他合法值,则输入行仅由给定字符串终止,并且行结尾将返回给calleruntranslated.
  • 当将输出写入流时,如果换行None,则写入的任何"\n"字符都将转换为系统默认行分隔符,os.linesep。如果换行"""\n",没有翻译的地方。如果换行符是任何其他合法值,则所写的任何"\n"字符都会被翻译成给定的字符串.

如果 line_buffering Trueflush()在调用towrite包含换行符或回车符时隐含。

如果 write_through True,保证不会缓冲对write()的调用:TextIOWrapper对象上写的任何数据都是立即的处理它的底层二进制缓冲区

在版本3.3中更改: 写入参数已被添加。

在版本3.3中更改:默认编码现在是locale.getpreferredencoding(False)而不是locale.getpreferredencoding()。不要使用locale.setlocale()更改临时的thelocale编码,使用当前的localeencoding而不是用户首选编码。

TextIOWrapper除了TextIOBase及其父母之外,还提供这些成员:

line_buffering
是否启用了行缓冲.
write_through
是否将写入立即传递给基础二进制缓冲区。

版本3.7中的新内容.
reconfigure * [,encoding] [,errors] [,换行符] [,line_buffering] [,write_through]
使用编码的新设置重新配置此文本流错误换行 line_buffering write_through

未指定的参数保持当前设置,除了errors="strict指定编码错误未指定。

如果已从流中读取某些数据,则无法更改编码或换行符。另一方面,写入后的changingencoding是可能的。

此方法在设置新参数之前执行隐式流刷新。

版本3.7.
class io.StringIO initial_value =“” newline =“\ n”
文本I / O的内存中流。调用close()方法时,将丢弃文本缓冲区。

可以通过提供initial_value来设置缓冲区的初始值。如果启用了换行符,则换行符将被编码为write()。流位于缓冲区的起始处。

换行参数的作用类似于TextIOWrapper。默认是只考虑\n字符作为行的结尾而不进行换行。如果换行符设置为None,则换行符在所有平台上写为\n,但在读取时仍会执行universalnewline解码。

StringIO提供此方法以及TextIOBase及其父母的方法:

getvalue
返回str包含缓冲区的全部内容。新行解码就好像是read(),尽管如此溪流位置没变.

用法示例:

import iooutput = io.StringIO()
output.write("First line.")
print("Second line.", file=output)

# Retrieve file contents -- this will be
# "First line.Second line."
contents = output.getvalue()

# Close object and discard memory buffer --
# .getvalue() will now raise an exception.
output.close()

 

class io.IncrementalNewlineDecoder
帮助编解码器解码通用换行符 mode的换行符。它继承codecs.IncrementalDecoder

性能

本节讨论所提供的具体I / O实现的性能。

二进制I / O

通过读取和写入大块数据,即使用户要求单个字节,缓冲I / O也会隐藏调用和执行操作系统的无缓冲I / O例程的任何低效率。增益取决于OS和执行的I / O的风。例如,在某些现代操作系统(如Linux)上,无缓冲磁盘I / O可以与缓冲I / O一样快。然而,最重要的是,缓冲I / O提供了可预测的性能,无论平台和支持设备如何。因此,对于二进制数据,几乎总是优选使用缓冲I / O而不是无缓冲I / O.

文字I / O

二进制存储(例如文件)上的文本I / O明显慢于同一存储上的二进制I / O,因为它需要使用字符编解码器在单元和二进制数据之间进行转换。这可能会变得很明显地处理大量的文本数据,如大型日志文件。而且,TextIOWrapper.tell()TextIOWrapper.seek()对于所使用的重建算法来说都非常慢。

StringIO然而,它是一个本机内存unicode容器,并且与BytesIO

多线程

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

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

TextIOWrapper对象不是线程安全的。

重入

二进制缓冲对象(BufferedReaderBufferedWriterBufferedRandomBufferedRWPair)不是可重入的。虽然在正常情况下不会发生可重入呼叫,但是在中进行I O时可能会出现这种情况signal处理程序。如果一个线程试图重新输入它已经访问的缓冲对象,那么RuntimeError被提出来了。请注意,这并不禁止其他线程进入缓冲对象。

以上隐含扩展到文本文件,因为open()functionWill将一个缓冲的对象包装在TextIOWrapper。这包括标准流,因此影响内置功能print()