15.2. io-使用流的核心工具

2.6 版的新Function。

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

Note

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

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

扩展IOBaseRawIOBase,它仅处理原始字节对流的读写。 FileIO子类RawIOBase为机器文件系统中的文件提供接口。

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

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

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

15.2.1. 模块接口

  • io. DEFAULT_BUFFER_SIZE

    • 一个 int,包含模块的缓冲 I/O 类使用的默认缓冲区大小。 open()尽可能使用文件的 blksize(由os.stat()获取)。
  • io. open(* file mode ='r' buffering = -1 encoding = None errors = None newline = None closefd = True *)

    • 打开* file *并返回相应的流。如果无法打开文件,则会引发IOError
  • file 是给出要打开文件的路径名(绝对或相对于当前工作目录)的字符串,或者是要包装文件的整数文件 Descriptors。 (如果给出了文件 Descriptors,除非 closefd *设置为False,否则它在关闭返回的 I/O 对象时将关闭.)

  • mode 是一个可选字符串,用于指定打开文件的模式。默认为'r',表示可以在文本模式下阅读。其他常用值包括'w'用于写入(如果文件已经存在,则将其截断)和'a'用于附加(在某些 Unix 系统上,这意味着 all 会将附加写入文件的末尾,而不管当前查找位置如何)。 。在文本模式下,如果未指定 encoding ,则使用的编码取决于平台。 (要读取和写入原始字节,请使用二进制模式,而未指定 encoding *.)可用模式为:

CharacterMeaning
'r'打开以供阅读(默认)
'w'打开进行写入,先截断文件
'a'打开进行写入,如果存在则追加到文件末尾
'b'binary mode
't'Literals 模式(默认)
'+'打开磁盘文件以进行更新(读取和写入)
'U'通用换行模式(为了向后兼容;不应在新代码中使用)

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

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

  • buffering 是用于设置缓冲策略的可选整数。传递 0 来关闭缓冲(仅在二进制模式下允许),传递 1 来选择行缓冲(仅在文本模式下可用),并传递一个大于 1 的整数以指示固定大小的块缓冲区的大小。如果不指定 buffering *参数,则默认的缓冲策略如下:
  • 二进制文件以固定大小的块缓冲;缓冲区的大小是pass试探法来确定底层设备的“块大小”并回退到DEFAULT_BUFFER_SIZE来选择的。在许多系统上,缓冲区的长度通常为 4096 或 8192 字节。

  • “交互式”文本文件(isatty()返回 True 的文件)使用行缓冲。其他文本文件将上述策略用于二进制文件。

  • encoding *是用于解码或编码文件的编码名称。仅应在文本模式下使用。默认编码取决于平台(无论locale.getpreferredencoding()返回什么),但是可以使用 Python 支持的任何编码。有关支持的编码列表,请参见codecs模块。

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

  • newline *控制universal newlines的工作方式(仅适用于文本模式)。可以是None'''\n''\r''\r\n'。其工作方式如下:

  • Importing 时,如果* newline *为None,则启用通用换行模式。Importing 中的行可以以'\n''\r''\r\n'结尾,并且在返回给调用者之前将其转换为'\n'。如果为'',则启用通用换行模式,但是行结尾未翻译地返回给呼叫者。如果它具有任何其他合法值,则 Importing 行仅由给定的字符串终止,并且该行的末尾不翻译就返回给调用方。

  • 在输出中,如果* newline None,则写入的任何'\n'字符都将转换为系统默认的行分隔符os.linesep。如果 newline '',则不会进行翻译。如果 newline *是其他任何合法值,则将写入的任何'\n'字符转换为给定的字符串。

如果* closefd False并且给出了文件 Descriptors 而不是文件名,则在关闭文件时,底层文件 Descriptors 将保持打开状态。如果给定文件名, closefd *无效,并且必须为True(默认值)。

open()函数返回的文件对象的类型取决于模式。当使用open()以文本模式('w''r''wt''rt'等)打开文件时,它将返回TextIOBase的子类(特别是TextIOWrapper)。当使用带缓冲的二进制模式打开文件时,返回的类是BufferedIOBase的子类。确切的类有所不同:在读取二进制模式下,它返回BufferedReader;在写二进制和追加二进制模式下,它返回BufferedWriter,而在读/写模式下,它返回BufferedRandom。禁用缓冲后,将返回原始流RawIOBaseFileIO的子类。

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

  • exception io. BlockingIOError
    • 在非阻塞流上发生阻塞时引发的错误。它继承了IOError

除了IOError之外,BlockingIOError还具有一个属性:

  • characters_written

    • 一个整数,包含在阻止之前写入流的字符数。
  • exception io. UnsupportedOperation

    • 在流上调用不受支持的操作时引发的继承IOErrorValueError的异常。

15.2.2. I/O 基本类别

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

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

尽管IOBase不会语句read()readinto()write(),因为它们的签名会有所不同,但实现和 Client 端应将这些方法视为接口的一部分。此外,在调用不支持的操作时,实现可能会引发IOError

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

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

请注意,在关闭的流上调用任何方法(甚至查询)都是未定义的。在这种情况下,实现可能会引发IOError

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

IOBase 还是上下文 Management 器,因此支持with语句。在此示例中,* file *在with语句的套件完成后关闭-即使发生异常:

with io.open('spam.txt', 'w') as file:
    file.write(u'Spam and eggs!')

IOBase提供了以下数据属性和方法:

  • close ( )
    • 冲洗并关闭此流。如果文件已经关闭,则此方法无效。关闭文件后,对该文件进行的任何操作(例如读取或写入)都将引发ValueError

为方便起见,允许多次调用此方法。但是,只有第一个电话才会生效。

  • closed

    • 如果流关闭,则为 True。
  • fileno ( )

    • 返回流的基础文件 Descriptors(整数)(如果存在)。如果 IO 对象不使用文件 Descriptors,则引发IOError
  • flush ( )

    • 刷新流的写缓冲区(如果适用)。这对只读流和非阻塞流不起作用。
  • isatty ( )

    • 如果流是交互式的(即连接到终端/ tty 设备),则返回True
  • readable ( )

    • 如果可以读取流,则返回True。如果False,则read()将加注IOError
  • readline(* limit = -1 *)

    • 从流中读取并返回一行。如果指定了* limit ,则最多将读取 limit *个字节。

对于二进制文件,行终止符始终为b'\n';对于文本文件,open()的* newline *参数可用于选择识别的行终止符。

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

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

  • seek(* offset whence = SEEK_SET *)

    • 将流位置更改为给定的字节* offset *。 * offset 相对于 whence *指示的位置进行解释。 * whence *的默认值为SEEK_SET。 * whence *的值是:
  • SEEK_SET0 –流的开始(默认); 偏移量应为零或正数

  • SEEK_CUR1 –当前流位置; 偏移量可能为负

  • SEEK_END2 –流的结尾; 偏移通常为负

返回新的绝对位置。

2.7 版的新Function:SEEK_*常量

  • seekable ( )

  • tell ( )

    • 返回当前流的位置。
  • truncate(* size = None *)

    • 将流的大小调整为给定的* size (以字节为单位)(如果未指定 size *,则调整为当前位置)。当前流的位置不变。调整大小可以扩展或减小当前文件的大小。对于 extensions,新文件区域的内容取决于平台(在大多数系统上,其他字节为零填充,而在 Windows 上则不确定)。返回新的文件大小。
  • writable ( )

    • 如果流支持写入,则返回True。如果Falsewrite()truncate()将加注IOError
  • writelines()

    • 将行列表写入流中。不添加行分隔符,因此通常为每个提供的行的末尾都具有行分隔符。
  • __del__ ( )

    • 准备销毁对象。 IOBase提供了此方法的默认实现,该方法调用实例的close()方法。
  • 类别 io. RawIOBase

    • 原始二进制 I/O 的 Base Class。它继承了IOBase。没有公共构造函数。

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

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

  • read(* n = -1 *)
    • 从对象读取最多* n 个字节并返回它们。为方便起见,如果未指定 n 或-1,则调用readall()。否则,只会进行一次系统调用。如果 os 调用返回的字节数少于 n 个字节,则可能返回少于 n *个字节。

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

  • readall ( )

    • 从流中读取并返回所有字节,直到 EOF,如有必要,可以使用多次调用流。
  • readinto(* b *)

    • 最多将 len(b)个字节读入* b ,并返回读取的字节数。对象 b *应该是预分配的可写字节数组,bytearraymemoryview。如果对象处于非阻塞模式并且没有字节可用,则返回None
  • write(* b *)

    • 将* b 写入基础原始流,并返回写入的字节数。对象 b 应该是字节数组,bytesbytearraymemoryview。返回值可以小于len(b),具体取决于基础原始流的细节,尤其是在非阻塞模式下。如果将原始流设置为不阻塞并且无法轻易将单个字节写入,则返回None。在此方法返回之后,调用者可以释放或更改 b ,因此实现应仅在方法调用期间访问 b *。
  • 类别 io. BufferedIOBase

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

RawIOBase的主要区别在于,方法read()readinto()write()会(分别)try读取请求的任意数量的 Importing 或消耗所有给定的输出,但以进行多个系统调用为代价。

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

此外,read()方法没有默认实现readinto()

典型的BufferedIOBase实现不应继承自RawIOBase实现,而应像BufferedWriterBufferedReader那样包装一个。

BufferedIOBase除了提供IOBase中的方法和属性外,还提供或覆盖这些方法和属性:

  • raw

  • detach ( )

    • 将底层原始流与缓冲区分开,然后将其返回。

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

某些缓冲区(例如BytesIO)没有从该方法返回单个原始流的概念。他们加注UnsupportedOperation

2.7 版的新Function。

  • read(* n = -1 *)
    • 读取并返回最多* n *个字节。如果Ellipsis该参数,None或否定参数,那么将读取并返回数据,直到达到 EOF。如果流已经在 EOF 上,则返回一个空字节对象。

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

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

  • read1(* n = -1 *)

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

    • 最多将 len(b)个字节读入* b ,并返回读取的字节数。对象 b *应该是预分配的可写字节数组,bytearraymemoryview

read()一样,可以对基础原始流进行多次读取,除非后者是“交互式的”。

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

  • write(* b *)
    • 写入* b ,并返回写入的字节数(始终等于len(b),因为如果写入失败,将引发IOError)。对象 b *应该是字节数组,bytesbytearraymemoryview。取决于实际的实现方式,这些字节可以很容易地写入底层流,或者出于性能和延迟原因,可以保留在缓冲区中。

在非阻塞模式下,如果需要将数据写入原始流,则它会引发BlockingIOError,但是如果不阻塞就无法接受所有数据。

在此方法返回之后,调用者可以释放或更改* b ,因此实现应仅在方法调用期间访问 b *。

15.2.3. 原始文件 I/O

    • class * io. FileIO(* name mode ='r' closefd = True *)
    • FileIO表示包含字节数据的 OS 级文件。它实现了RawIOBase接口(因此也实现了IOBase接口)。
  • name *可以是以下两项之一:
  • 一个字符串,表示将要打开的文件的路径;

  • 一个整数,表示结果FileIO对象将对其访问的现有 OS 级文件 Descriptors 的编号。

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

此类上的read()(使用正参数调用时),readinto()write()方法将仅进行一次系统调用。

除了IOBaseRawIOBase的属性和方法,FileIO还提供以下数据属性和方法:

  • mode

    • 构造函数中给定的模式。
  • name

    • 文件名当在构造函数中未给出名称时,这是文件的文件 Descriptors。

15.2.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 *)
    • 提供对可读的 SequencesRawIOBase对象的更高级别访问的缓冲区。它继承了BufferedIOBase。从此对象读取数据时,可能会从基础原始流中请求大量数据,并将其保存在内部缓冲区中。然后可以在后续读取时直接返回缓冲的数据。

构造函数为给定的可读* raw 流和 buffer_size 创建一个BufferedReader。如果Ellipsis 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 *)
    • 提供对可写 SequencesRawIOBase对象的更高级别访问的缓冲区。它继承了BufferedIOBase。写入该对象时,数据通常保存在内部缓冲区中。在各种情况下,该缓冲区将被写到基础RawIOBase对象中,包括:
  • 当缓冲区对于所有未决数据而言变得太小时;

  • flush()被调用时;

  • 当请求seek()时(对于BufferedRandom个对象);

  • BufferedWriter对象关闭或销毁时。

构造函数为给定的可写* raw 流创建一个BufferedWriter。如果未指定 buffer_size *,则默认为DEFAULT_BUFFER_SIZE

支持第三个参数* max_buffer_size *,但未使用且已弃用。

BufferedWriter除了BufferedIOBaseIOBase中的方法外,还提供或覆盖了这些方法:

  • flush ( )

    • 将保留在缓冲区中的字节强制进入原始流。如果原始流阻塞,则应引发BlockingIOError
  • write(* b *)

    • 写入* b ,并返回写入的字节数。对象 b *应该是字节数组,bytesbytearraymemoryview。在非阻塞模式下,如果需要写出缓冲区但原始流阻塞,则引发BlockingIOError
    • class * io. BufferedRandom(* raw buffer_size = DEFAULT_BUFFER_SIZE *)

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

支持第三个参数* max_buffer_size *,但未使用且已弃用。

BufferedRandom具备BufferedReaderBufferedWriter可以做的任何事情。

  • 类别 io. BufferedRWPair(读取器写入器,* buffer_size = DEFAULT_BUFFER_SIZE *)
    • 一个缓冲的 I/O 对象,将两个单向RawIOBase对象(一个可读,另一个可写)组合到一个双向端点中。它继承了BufferedIOBase

支持第四个参数* max_buffer_size *,但未使用且已弃用。

BufferedRWPair实现BufferedIOBase的所有方法,但detach()引发UnsupportedOperation除外。

Warning

BufferedRWPair不会try同步对其基础原始流的访问。您不应将其与读写器传递给同Pair象;请改用BufferedRandom

15.2.5. LiteralsImporting/输出

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

TextIOBase除了提供IOBase中的数据属性和方法外,还提供或覆盖这些数据属性和方法:

  • encoding

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

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

    • 一个字符串,一个字符串 Tuples 或None,指示到目前为止已翻译的换行符。取决于实现和初始构造函数标志,这可能不可用。
  • buffer

  • detach ( )

    • 将底层二进制缓冲区与TextIOBase分开并返回。

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

某些TextIOBase实现(例如StringIO)可能没有底层缓冲区的概念,调用此方法将引发UnsupportedOperation

2.7 版的新Function。

  • read(* n = -1 *)

    • 从流中读取并最多返回* n 个字符,作为单个unicode。如果 n *为负数或None,则读取直到 EOF。
  • readline(* limit = -1 *)

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

如果指定了* limit ,最多将读取 limit *个字符。

  • seek(* offset whence = SEEK_SET *)

    • 将流位置更改为给定的* offset 。行为取决于 whence *参数。 * whence *的默认值为SEEK_SET
  • SEEK_SET0:从流的开头开始搜索(默认); * offset 必须是TextIOBase.tell()返回的数字或零。任何其他 offset *值都会产生不确定的行为。

  • SEEK_CUR1:“搜索”到当前位置; * offset *必须为零,这是空操作(不支持所有其他值)。

  • SEEK_END2:搜索到流的结尾; 偏移必须为零(不支持所有其他值)。

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

2.7 版的新Function:SEEK_*常量。

  • tell ( )

    • 以不透明数字返回当前流的位置。该数字通常不表示基础二进制存储中的字节数。
  • write(* s *)

    • unicode字符串* s *写入流中,并返回写入的字符数。
    • class * io. TextIOWrapper(* buffer encoding = None errors = None newline = None line_buffering = False *)
  • encoding *给出将用于解码或编码流的编码的名称。默认为locale.getpreferredencoding()

  • errors *是一个可选的字符串,它指定如何处理编码和解码错误。如果存在编码错误,则传递'strict'引发ValueError异常(缺省值None具有相同的效果),或者传递'ignore'来忽略错误。 (请注意,忽略编码错误会导致数据丢失.)'replace'会导致在数据格式错误的地方插入替换标记(例如'?')。编写时,可以使用'xmlcharrefreplace'(用适当的 XML 字符引用替换)或'backslashreplace'(用反斜杠转义序列替换)。已向codecs.register_error()注册的任何其他错误处理名称也有效。

  • newline *控制行尾的处理方式。可以是None'''\n''\r''\r\n'。其工作方式如下:

  • Importing 时,如果* newline *为None,则启用universal newlines模式。Importing 中的行可以以'\n''\r''\r\n'结尾,并且在返回给调用者之前,这些行会转换为'\n'。如果是'',则启用通用换行模式,但是行结尾不翻译就返回给呼叫者。如果它具有任何其他合法值,则 Importing 行仅由给定的字符串终止,并且该行的末尾不翻译就返回给调用方。

  • 在输出中,如果* newline None,则写入的任何'\n'字符都将转换为系统默认的行分隔符os.linesep。如果 newline '',则不会进行翻译。如果 newline *是其他任何合法值,则将写入的任何'\n'字符转换为给定的字符串。

如果* line_buffering *为True,则在写调用包含换行符或回车符时隐含flush()

TextIOWrapper除了TextIOBase及其父项之外,还提供了一个属性:

  • line_buffering

    • 是否启用行缓冲。
    • class * io. StringIO(* initial_value = u'' newline = u' n'*)

可以pass提供* initial_value *来设置缓冲区的初始值。如果启用了换行翻译,则换行将被编码为write()。流位于缓冲区的开头。

  • newline 参数的作用类似于TextIOWrapper。默认设置是仅将\n个字符视为行尾,并且不进行换行翻译。如果将 newline *设置为None,则在所有平台上将换行符写入为\n,但是在读取时仍会执行通用换行符解码。

StringIO除了TextIOWrapper及其父级提供的方法外,还提供了此方法:

  • getvalue ( )
    • 在调用StringIO对象的close()方法之前的任何时候,返回一个包含缓冲区全部内容的unicode。尽管没有更改流的位置,但换行符的解码方式好像是由read()进行解码的。

Example usage:

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()

15.2.6. 进阶主题

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

15.2.6.1. Performance

15.2.6.1.1. 二进制 I/O

pass即使在用户要求单个字节时也仅读取和写入大块数据,缓冲的 I/O 旨在隐藏调用和执行 os 的非缓冲 I/O 例程时的任何低效率。增益的变化取决于 os 和执行的 I/O 种类(例如,在某些现代的 OS(例如 Linux)上,未缓冲的磁盘 I/O 可以与缓冲的 I/O 一样快)。最重要的是,无论平台和支持设备如何,缓冲的 I/O 都能为您提供可预测的性能。因此,最总是最好使用缓冲 I/O 而不是未缓冲 I/O。

15.2.6.1.2. LiteralsImporting/输出

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

StringIO是内存中的本地 unicode 容器,其显示速度与BytesIO类似。

15.2.6.2. Multi-threading

FileIO对象是线程安全的,以至于它们包装的 os 调用(例如 Unix 下的read(2))也是线程安全的。

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

TextIOWrapper对象不是线程安全的。

15.2.6.3. Reentrancy

二进制缓冲对象(实例BufferedReaderBufferedWriterBufferedRandomBufferedRWPair)不可重入。虽然在正常情况下不会发生可重入调用,但是如果您在signal处理程序中执行 I/O,则可能会发生重调用。如果试图从同一个线程访问*时再次 Importing 一个缓冲对象,则会引发RuntimeError

上面的内容隐含地扩展到文本文件,因为open()函数会将缓冲的对象包装在TextIOWrapper内。这包括标准流,因此也会影响内置函数print()