首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

io

2.6版本中的新功能。

io模块为流处理提供了Python接口。在Python 2.x中,这是建议作为内置file对象的替代方法,但在Python 3.x中,它是访问文件和流的默认接口。

注意

由于此模块主要是为Python 3.x设计的,因此您必须注意,本文档中“字节”的所有用法均指str类型(其bytes为别名),“text”的所有用法均指unicode类型。而且,这两种类型在ioAPI 中不可互换。

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

扩展IOBaseRawIOBase简单地处理原始字节到流的读取和写入。FileIO子类RawIOBase为机器文件系统中的文件提供接口。

BufferedIOBase处理原始字节流(RawIOBase)上的缓冲。它的子类,BufferedWriterBufferedReader,和BufferedRWPair缓冲流是可读,可写,以及可读写的。BufferedRandom为随机访问流提供缓冲接口。BytesIO是一个简单的内存中字节流。

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

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

1.模块接口

io.DEFAULT_BUFFER_SIZE

包含模块的缓冲I / O类使用的默认缓冲区大小的int。如果可能的话,open()使用文件的blksize(通过获得os.stat())。

io.open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)

打开文件并返回相应的流。如果文件无法打开,IOError则会提出。

file是要打开的文件的路径名(绝对或相对于当前工作目录)或要打包的文件的整数文件描述符。(如果给出文件描述符,则在返回的I / O对象关闭时关闭,除非closefd设置为False。)

mode是一个可选字符串,用于指定打开文件的模式。它默认'r'打开文本模式下的阅读方式。其他常见的值是'w'写入(如果文件已经存在,则截断该文件)以及'a'追加(在某些 Unix系统上,这意味着无论当前的搜索位置如何,所有写入都追加到文件末尾)。在文本模式下,如果编码未指定使用的编码是依赖于平台。(用于读取和写入原始字节使用二进制模式并且未指定编码。)可用的模式有:

字符

含义

'R'

打开阅读(默认)

'W'

打开写入,首先截断文件

'a'

打开写入,追加到文件末尾(如果存在)

'B'

二进制模式

'T'

文本模式(默认)

'+'

打开磁盘文件进行更新(读取和写入)

'U'

通用换行符模式(向后兼容;不应在新代码中使用)

默认模式是'rt'(打开阅读文本)。对于二进制随机访问,该模式'w+b'打开并截断文件为0字节,同时'r+b'打开文件而不截断。

Python区分以二进制和文本模式打开的文件,即使底层操作系统没有。以二进制模式打开的文件(包括'b'模式参数中)以bytes没有任何解码的对象的形式返回内容。在文本模式下(默认情况下,或者't'包含在mode参数中时),文件的内容以unicode字符串形式返回,字节首先使用平台相关编码进行解码,或者使用指定的编码(如果给出)。

缓冲是用于设置缓冲策略的可选整数。通过0切换缓冲关闭(仅在二进制模式下允许),1选择行缓冲(仅在文本模式下可用),以及> 1的整数以指示固定大小的块缓冲区的大小。如果未给出缓冲参数,则默认缓冲策略的工作方式如下所示:

  • 二进制文件以固定大小的块进行缓冲; 缓冲区的大小是通过试图确定底层设备的“块大小”并重新开始的启发式来选择的DEFAULT_BUFFER_SIZE。在很多系统上,缓冲区的长度通常为4096或8192字节。
  • “交互式”文本文件(isatty()返回True的文件)使用行缓冲。其他文本文件使用上述的二进制文件策略。

编码是用于解码或编码文件的编码的名称。这只能用于文本模式。默认编码依赖于平台(无论locale.getpreferredencoding()返回),但可以使用Python支持的任何编码。请参阅codecs模块以获取支持的编码列表。

错误是一个可选字符串,指定如何处理编码和解码错误 - 这不能用于二进制模式。如果存在编码错误(默认设置具有相同效果),则通过'strict'以引发ValueError异常None,或通过'ignore'以忽略错误。(请注意,忽略编码错误可能会导致数据丢失。)'replace'会导致将替换标记(例如'?')插入存在格式错误的数据的位置。在编写时,'xmlcharrefreplace'(用适当的XML字符引用'backslashreplace'替换)或(用反斜杠转义序列替换)可以使用。任何其他已经注册的错误处理名称codecs.register_error()也是有效的。

换行符控制通用换行符的工作方式(仅适用于文本模式)。它可以是None'''\n''\r',和'\r\n'。它的工作原理如下:

  • 在输入时,如果换行符None,则启用通用换行符模式。输入中的行可以以'\n',,'\r'或结束'\r\n',并且'\n'在返回给调用者之前将这些行翻译成。如果是'',则启用通用换行符模式,但行结束符将返回给调用方未翻译。如果它具有任何其他合法值,则输入行仅由给定字符串终止,并且行尾以未翻译形式返回给调用者。
  • 在输出时,如果换行符None,则'\n'写入的任何字符都将转换为系统默认的行分隔符os.linesep。如果换行'',则不会发生翻译。如果换行符是任何其他合法值,则'\n'写入的任何字符都将转换为给定的字符串。

如果closefdFalse文件描述符而不是文件名,那么文件关闭时底层文件描述符将保持打开状态。如果给定文件名closefd没有效果并且必须是True(默认)。

open()函数返回的文件对象的类型取决于模式。当open()使用在文本模式(打开一个文件'w''r''wt''rt',等等),它返回的一个子类TextIOBase(具体而言TextIOWrapper)。当用缓冲区以二进制模式打开文件时,返回的类是其子类BufferedIOBase。确切的类有所不同:在读取二进制模式下,它返回一个BufferedReader; 在写入二进制和附加二进制模式下,它返回一个BufferedWriter,并在读/写模式下,它返回一个BufferedRandom。当缓冲被禁用,原始流,的一个子类RawIOBaseFileIO,则返回。

也可以使用一个字符串unicodebytes字符串作为文件来读取和写入。对于unicode字符串StringIO可用于像在文本模式下打开的文件,和bytes一个BytesIO可以像在二进制模式打开的文件中。

exception io.BlockingIOError

在非阻塞流上发生阻塞时引发错误。它继承IOError

除了那些之外IOErrorBlockingIOError还有一个属性:

characters_written

包含在阻塞之前写入流的字符数的整数。

exception io.UnsupportedOperation

例外的继承IOErrorValueError当不支持的操作上调用流时引发。

2. I / O基类

class io.IOBase

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

此类为许多派生类可以选择性覆盖的方法提供了空抽象实现; 默认实现代表无法读取,写入或查找的文件。

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

用于从文件读取或写入文件的二进制数据的基本类型bytes(也称为str)。方法参数也可以是字节数组bytearraymemoryview字节数组。在某些情况下,例如需要readinto()的可写对象bytearray。文本I / O类使用unicode数据。

在版本2.7中更改:实现应支持memoryview参数。

请注意,调用封闭流中的任何方法(即使是查询)都是未定义的。IOError在这种情况下,实现可能会提高。

IOBase(及其子类)支持迭代器协议,这意味着IOBase可以通过产生流中的行来迭代对象。根据流是二进制流(yielding bytes)还是文本流(产生unicode字符串),行的定义略有不同。见readline()下文。

IOBase也是上下文管理器,因此支持该with声明。在这个例子中,文件with声明套件结束后关闭- 即使发生异常:

代码语言:javascript
复制
with io.open('spam.txt', 'w') as file:
    file.write(u'Spam and eggs!')

IOBase 提供这些数据属性和方法:

close()

冲洗并关闭此流。如果该文件已关闭,则此方法无效。一旦文件关闭,对文件的任何操作(例如读或写)都会引发一次ValueError

为了方便,可以多次调用此方法; 然而,只有第一个电话会起作用。

closed

如果流关闭,则为真。

fileno()

返回流的底层文件描述符(整数)(如果存在)。一个IOError如果IO对象不使用文件描述符提高。

flush()

刷新流的写入缓冲区(如果适用)。这对于只读流和非阻塞流没有任何作用。

isatty()

返回True如果流是交互式(即,连接到一个终端/ TTY设备)。

readable()

如果可以从中读取流,则返回True。如果Falseread()会提高IOError

readline(limit=-1)

从流中读取并返回一行。如果限制被指定,在最极限的字节将被读取。

行结束符总是b'\n'用于二进制文件; 对于文本文件,可以使用换行符参数来open()选择识别的行结束符。

readlines(hint=-1)

从流中读取并返回行列表。可以指定提示来控制读取的行数:如果所有行的总大小(字节/字符)超过提示,则不会再读取行。

请注意,已经可以在for line in file: ...不调用的情况下迭代文件对象file.readlines()

seek(offset[, whence])

将流位置更改为给定的字节偏移量偏移是相对于由指示的位置解释何处whence 的默认值是SEEK_SET从哪里来的价值是:

  • SEEK_SET0- 流的开始(默认); 偏移应为零或正数
  • SEEK_CUR1- 当前流位置; 抵消可能是负面的
  • SEEK_END2- 流的结尾; 抵消通常是负面的

返回新的绝对位置。

2.7版本中的新功能:SEEK_*常量

seekable()

如果流支持随机访问,则返回True。如果Falseseek()tell()并且truncate()将提高IOError

tell()

返回当前的流位置。

truncate(size=None)

将流大小调整为以字节为单位的给定大小(如果未指定大小,则将其大小设置为当前位置)。当前流的位置不变。此调整大小可以扩展或减少当前文件大小。在扩展的情况下,新文件区的内容取决于平台(在大多数系统上,额外的字节是零填充的,在Windows中它们是未确定的)。新的文件大小被返回。

writable()

如果流支持写入,则返回True如果流支持写入,则返回。如果Falsewrite()并且truncate()会升高IOError

writelines(lines)

写入流列表。没有添加行分隔符,因此通常提供的每行都在末尾具有行分隔符。

__del__()

准备对象销毁。IOBase提供了调用实例close()方法的此方法的默认实现。

class io.RawIOBase

原始二进制I / O的基类。它继承IOBase。没有公共构造函数。

原始二进制I / O通常提供对底层操作系统设备或API的低级别访问,并且不会尝试将其封装在高级基元中(这留给了缓冲I / O和文本I / O,稍后会在本文中进行描述页)。

除了属性和方法外IOBase,RawIOBase还提供了以下方法:

read(n=-1)

从对象中读取n个字节并返回它们。为方便起见,如果n未指定或-1,readall()则调用。否则,只会有一次系统调用。不到ñ如果操作系统调用返回少于字节可以返回ñ个字节。

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

readall()

读取并返回流中的所有字节,直到EOF,如有必要,使用多个对流的调用。

readinto(b)

将len(b)字节读入b,并返回读取的字节数。对象b应的字节的预分配的,可写入的阵列,无论是bytearraymemoryview。如果对象处于非阻塞模式并且没有可用字节,None则返回。

write(b)

b写入基础原始流,并返回写入的字节数。对象b应是一个字节数组,无论是bytesbytearray,或memoryview。返回值可以小于len(b),取决于基础原始流的细节,尤其是处于非阻塞模式时。None如果原始流设置为不阻塞,并且没有单个字节可以很容易地写入它,则返回。调用者可以在此方法返回后释放或变异b,因此实现应该只在方法调用期间访问b

class io.BufferedIOBase

支持某种缓冲的二进制流的基类。它继承IOBase。没有公共构造函数。

主要的区别RawIOBase在于方法read()readinto()并且write()将尝试(分别)读取尽可能多的输入,或者消耗所有给定的输出,但可能会造成多次系统调用。

另外,BlockingIOError如果基础原始数据流处于非阻塞模式并且不能提取或提供足够的数据,那么可以引发这些方法; 不像他们的RawIOBase同行,他们永远不会回来None

此外,该read()方法没有遵循的默认实现readinto()

一个典型的BufferedIOBase实现不应该从继承RawIOBase的实现,但是一个包,喜欢BufferedWriterBufferedReader这样做。

BufferedIOBase提供或覆盖这些方法和属性以及来自以下的方法和属性IOBase

raw

处理的基础原始流(RawIOBase实例)BufferedIOBase。这不是BufferedIOBaseAPI的一部分,在某些实现中可能不存在。

detach()

将底层原始流从缓冲区中分离出来并返回。

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

一些缓冲区,例如BytesIO,没有从此方法返回的单个原始流的概念。他们提高UnsupportedOperation

2.7版本的新功能。

read(n=-1)

读取并返回最多n个字节。如果参数被省略,None或者为负数,则读取并返回数据直到达到EOF。如果流已经在EOF,则返回空字节对象。

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

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

read1(n=-1)

读取并返回最多n个字节,最多只需调用一次基础原始流的read()方法。如果你在一个BufferedIOBase对象上实现自己的缓冲,这会很有用。

readinto(b)

将len(b)字节读入b,并返回读取的字节数。对象b应的字节的预分配的,可写入的阵列,无论是bytearraymemoryview

同样read(),可能会向基础原始流发布多个读取,除非后者是“交互式”的。

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

write(b)

写入b,并返回写入的字节数(总是等于len(b),因为如果写入失败,IOError将会引发)。对象b应是一个字节数组,无论是bytesbytearray,或memoryview。根据实际的实现情况,这些字节可能很容易写入基础流,或者由于性能和延迟原因而保存在缓冲区中。

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

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

3.原始文件I / O

class io.FileIO(name, mode='r', closefd=True)

FileIO表示包含字节数据的OS级文件。它实现了RawIOBase接口(因此也实现了接口IOBase)。

这个名字可以是以下两件事之一:

  • 表示将要打开的文件的路径的字符串;
  • 一个整数,表示生成的FileIO对象将访问的现有OS级文件描述符的编号。

模式可以是'r''w'或者'a'用于读取(默认),写入或追加。如果文件在打开或写入时不存在,则该文件将被创建; 它会在写入时被截断。'+'将模式添加到允许同时读取和写入的模式。

read()(与积极的参数调用),readinto()write()在这个类的方法只会让一个系统调用。

除了从属性和方法IOBase以及RawIOBaseFileIO提供了以下的数据的属性和方法:

mode

在构造函数中给出的模式。

name

文件名称。这是在构造函数中没有给出名称时该文件的文件描述符。

4.缓冲流

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

class io.BytesIO([initial_bytes])

使用内存中字节缓冲区的流实现。它继承BufferedIOBase

可选参数initial_bytes是一个bytes包含初始数据的对象。

BytesIO提供或覆盖除了那些从这些方法BufferedIOBaseIOBase

getvalue()

返回bytes包含缓冲区的全部内容。

read1()

BytesIO,这是一样的read()

class io.BufferedReader(raw, buffer_size=DEFAULT_BUFFER_SIZE)

缓冲区提供对可读,顺序RawIOBase对象的更高级访问。它继承BufferedIOBase。从这个对象读取数据时,可能会从基础原始数据流请求更大量的数据,并将其保存在内部缓冲区中。缓存的数据可以在随后的读取中直接返回。

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

BufferedReader提供或覆盖除了那些从这些方法BufferedIOBaseIOBase

peek([n])

返回流中的字节而不推进位置。对原始流最多进行一次读取以满足呼叫。返回的字节数可能少于或多于请求的数量。

read([n])

读取并返回n个字节,或者如果n未给出或为负数,则直到EOF或者读取调用将在非阻塞模式下阻塞。

read1(n)

在原始流上只有一个调用读取并返回n个字节。如果至少有一个字节被缓存,则只返回缓冲的字节。否则,会创建一个原始流读取调用。

class io.BufferedWriter(raw, buffer_size=DEFAULT_BUFFER_SIZE)

提供对可写入,顺序RawIOBase对象的更高级别访问的缓冲区。它继承BufferedIOBase。写入此对象时,数据通常保存在内部缓冲区中。缓冲区将RawIOBase在各种条件下写入到底层对象,包括:

  • 当缓冲区对于所有未决数据而言太小时;
  • flush()被调用;
  • seek()被请求时(BufferedRandom对象);
  • BufferedWriter物体被关闭或毁坏时。

构造函数BufferedWriter为给定的可写原始流创建一个。如果没有给出buffer_size,则默认为DEFAULT_BUFFER_SIZE

第三个参数max_buffer_size支持,但未使用且不推荐使用。

BufferedWriter提供或覆盖除了那些从这些方法BufferedIOBaseIOBase

flush()

强制缓冲区中保存的字节流入原始流。BlockingIOError如果原始流阻塞,则应该提出A.

write(b)

写入b,并返回写入的字节数。对象b应是一个字节数组,无论是bytesbytearray,或memoryview。处于非阻塞模式时,BlockingIOError如果需要写出缓冲区但未加工的流阻止,则会引发a 。

class io.BufferedRandom(raw, buffer_size=DEFAULT_BUFFER_SIZE)

随机访问流的缓冲接口。它继承BufferedReaderBufferedWriter进一步的支持seek()tell()功能。

构造函数为第一个参数中给出的可搜索原始流创建一个读取器和写入器。如果buffer_size被省略,则默认为DEFAULT_BUFFER_SIZE

第三个参数max_buffer_size支持,但未使用且不推荐使用。

BufferedRandom有能力做任何事情BufferedReaderBufferedWriter能做。

class io.BufferedRWPair(reader, writer, buffer_size=DEFAULT_BUFFER_SIZE)

一个缓冲I / O对象,将两个单向RawIOBase对象(一个可读,另一个可写)组合为单个双向端点。它继承BufferedIOBase

读取器写入器RawIOBase分别是可读且可写的对象。如果buffer_size被省略,则默认为DEFAULT_BUFFER_SIZE

第四个参数max_buffer_size受支持,但未使用且不推荐使用。

BufferedRWPair实现BufferedIOBase除了detach()引发的所有方法UnsupportedOperation

警告

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

5.文本I / O

class io.TextIOBase

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

TextIOBase提供或覆盖这些数据属性和方法,以及来自以下方面的数据属性和方法IOBase

encoding

用于将流的字节解码为字符串并将字符串编码为字节的编码名称。

errors

解码器或编码器的错误设置。

newlines

一个字符串,一个字符串元组,或者None,表示到目前为止翻译的换行符。根据实现和初始构造函数标志,这可能不可用。

buffer

基本的二进制缓冲区(一个BufferedIOBase实例)TextIOBase处理。这不是TextIOBaseAPI的一部分,在某些实现中可能不存在。

detach()

分离底层二进制缓冲区TextIOBase并将其返回。

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

一些TextIOBase实现,比如StringIO,可能没有底层缓冲的概念,并且调用这个方法会提高UnsupportedOperation

2.7版本的新功能。

read(n)

从流中读取并返回至多n个字符作为单个字符unicode。如果n为负数None,则直到EOF读取。

readline(limit=-1)

阅读直到换行或EOF并返回一个unicode。如果流已经在EOF中,则返回空字符串。

如果指定了限制,则至多限制字符将被读取。

seek(offset[, whence])

将流位置更改为给定的偏移量。行为取决于哪个参数。whence的默认值是SEEK_SET

  • SEEK_SET或者0:从流的开头寻找(默认); 偏移量必须是返回的数字TextIOBase.tell()或零。任何其他偏移值都会产生未定义的行为。
  • SEEK_CUR或者1:“寻找”到当前位置; 偏移必须为零,这是一个无操作(所有其他值不受支持)。
  • SEEK_END或者2:寻求流的结束; 偏移量必须为零(所有其他值不受支持)。

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

2.7版本中的新功能:SEEK_*常量。

tell()

将当前流位置作为不透明数字返回。该数字通常不代表底层二进制存储中的字节数。

write(s)

unicode字符串s写入流并返回写入的字符数。

class io.TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False)

一个BufferedIOBase二进制流缓冲的文本流。它继承TextIOBase

编码给出了流将被解码或编码的编码的名称。它默认为locale.getpreferredencoding()

错误是一个可选字符串,指定如何处理编码和解码错误。如果存在编码错误(默认设置具有相同效果),则通过'strict'以引发ValueError异常None,或通过'ignore'以忽略错误。(请注意,忽略编码错误可能会导致数据丢失。)'replace'会导致将替换标记(例如'?')插入存在格式错误的数据的位置。在编写时,'xmlcharrefreplace'(用适当的XML字符引用'backslashreplace'替换)或(用反斜杠转义序列替换)可以使用。任何其他已经注册的错误处理名称codecs.register_error()也是有效的。

换行符控制着行结束的处理方式。它可以是None'''\n''\r',和'\r\n'。它的工作原理如下:

  • 在输入时,如果换行符None,则启用通用换行符模式。输入中的行可以以'\n',,'\r'或结束'\r\n',并且'\n'在返回给调用者之前将这些行翻译成。如果是'',则启用通用换行符模式,但行结束符将返回给调用方未翻译。如果它具有任何其他合法值,则输入行仅由给定字符串终止,并且行尾以未翻译形式返回给调用者。
  • 在输出时,如果换行符None,则'\n'写入的任何字符都将转换为系统默认的行分隔符os.linesep。如果换行'',则不会发生翻译。如果换行符是任何其他合法值,则'\n'写入的任何字符都将转换为给定的字符串。

如果line_bufferingTrueflush()则在写入调用包含换行符时隐含。

TextIOWrapper除了那些TextIOBase和它的父母之外还提供了一个属性:

line_buffering

线路缓冲是否启用。

class io.StringIO(initial_value=u'', newline=u'\n')

用于unicode文本的内存中的流。它继承TextIOWrapper

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

新行的说法就像是的TextIOWrapper。默认情况下,只考虑\n字符作为行的末尾,并且不执行换行。如果换行符设置为None,则换行符会\n在所有平台上写入,但通用换行符解码在读取时仍然执行。

StringIO除了来自TextIOWrapper其父母的方法外,还提供了此方法:

getvalue()

unicode在调用StringIO对象的close()方法之前,随时返回一个包含缓冲区全部内容的a 。换行符被解码read(),尽管流位置没有改变。

用法示例:

代码语言:javascript
复制
import io

output = io.StringIO()
output.write(u'First line.\n')
output.write(u'Second line.\n')

# Retrieve file contents -- this will be
# u'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

6.高级主题

在这里我们将讨论与上述具体I / O实现有关的几个高级主题。

6.1. 性能

6.1.1. 二进制I / O

即使用户要求单个字节,通过读取和写入大块数据,缓冲I / O也可以隐藏调用和执行操作系统的无缓冲I / O例程的任何低效率。根据操作系统和所执行的I / O类型(例如,在一些现代操作系统,如Linux,无缓冲磁盘I / O可以像缓冲I / O一样快),增益会有很大差异。然而,底线是缓冲I / O将为您提供可预测的性能,无论平台和支持设备如何。因此,最好总是使用缓冲I / O而不是无缓冲I / O。

6.1.2. 文本I / O

二进制存储(例如文件)上的文本I / O比同一存储上的二进制I / O慢得多,因为它意味着使用字符编解码器从Unicode到二进制数据的转换。如果您处理大量文本数据(例如非常大的日志文件),这会变得很明显。此外,TextIOWrapper.tell()TextIOWrapper.seek()都相当缓慢,由于使用的重建算法。

StringIO但是,它是一个本地内存unicode容器,并且会显示类似的速度BytesIO

6.2. 多线程

FileIO对象是线程安全的,以至于操作系统调用的程序(例如read(2)在Unix下)也是线程安全的。

二进制缓冲对象(的实例BufferedReaderBufferedWriterBufferedRandomBufferedRWPair)使用锁保护它们的内部结构; 因此从多个线程一次调用它们是安全的。

TextIOWrapper 对象不是线程安全的。

6.3. 重入

二进制缓冲对象(实例BufferedReaderBufferedWriterBufferedRandomBufferedRWPair)是不可重入。虽然在正常情况下不会发生可重入呼叫,但如果您在signal处理程序中执行I / O,则可能会出现这种情况。如果尝试在已经从同一线程访问时再次输入缓冲对象,则会RuntimeError引发。

上述隐式扩展到文本文件,因为open()函数会将缓冲对象包装在一个TextIOWrapper。这包括标准流,因此也影响内置功能print()

扫码关注腾讯云开发者

领取腾讯云代金券