# `io` --- 处理流的核心工具

源代码: Lib/io.py

## 概述

`io` 模块提供了 Python 用于处理各种 I/O 类型的主要工具。三种主要的 I/O类型分别为: 文本 I/O, 二进制 I/O 和 原始 I/O。这些是泛型类型，有很多种后端存储可以用在他们上面。一个隶属于任何这些类型的具体对象被称作 file object。 其他同类的术语还有 流 和 类文件对象。

独立于其类别，每个具体流对象也将具有各种功能：它可以是只读，只写或读写。它还可以允许任意随机访问（向前或向后寻找任何位置），或仅允许顺序访问（例如在套接字或管道的情况下）。

所有流对提供给它们的数据类型都很敏感。例如将 `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")

`TextIOBase` 的文档中详细描述了文本流的API

### 二进制 I/O

二进制I/O（也称为缓冲I/O）预期 bytes-like objects 并生成 `bytes` 对象。不执行编码、解码或换行转换。这种类型的流可以用于所有类型的非文本数据，并且还可以在需要手动控制文本数据的处理时使用。

创建二进制流的最简单方法是使用 `open()`，并在模式字符串中指定 `'b'` ：

    f = open("myfile.jpg", "rb")

内存中二进制流也可以作为 `BytesIO` 对象使用：

    f = io.BytesIO(b"some initial binary data: \x00\x01")

`BufferedIOBase` 的文档中详细描述了二进制流的API

其他库模块可以提供额外的方式来创建文本或二进制流。参见 `socket.socket.makefile()` 的示例。

### 原始 I/O

原始 I/O（也称为 非缓冲 I/O）通常用作二进制和文本流的低级构建块。用户代码直接操作原始流的用法非常罕见。不过，可以通过在禁用缓冲的情况下以二进制模式打开文件来创建原始流：

    f = open("myfile.jpg", "rb", buffering=0)

`RawIOBase` 的文档中详细描述了原始流的API

## 高阶模块接口

`io.``DEFAULT_BUFFER_SIZE`

  包含模块缓冲I/O类使用的默认缓冲区大小的整数。（如果可能） `open()` 将使用文件的blksize（由 `os.stat()` 获得）。

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

  这是内置的 `open()` 函数的别名。

  `open` 附带参数 `path`、`mode`、`flags` 会引发 审计事件。

`io.``open_code`(path)

  以 `'rb'` 模式打开提供的文件。如果目的是将文件内容做为可执行代码，则应使用此函数。

  `path` 应当为 `str` 类型并且是一个绝对路径。

  此函数的行为可以由对 `PyFile_SetOpenCodeHook()` 的先期调用所重载。 但是，如果 `path` 为 `str` 类型并且是一个绝对路径，`open_code(path)` 的行为应当总是与 `open(path, 'rb')` 一致。 重载此行为的目的是为了给文件附加额外的验证或预处理。

  3.8 新版功能.

exception `io.``BlockingIOError`

  这是内置的 `BlockingIOError` 异常的兼容性别名。

exception `io.``UnsupportedOperation`

  在流上调用不支持的操作时引发的继承 `OSError` 和 `ValueError` 的异常。

参见

`sys`

  包含标准IO流: `sys.stdin`, `sys.stdout` 和 `sys.stderr` 。

## 类的层次结构

I/O 流被安排为按类的层次结构实现。 首先是 抽象基类 (ABC)，用于指定流的各种类别，然后是提供标准流实现的具体类。

> 注解

> 抽象基类还提供某些方法的默认实现，以帮助实现具体的流类。例如 `BufferedIOBase` 提供了 `readinto()` 和 `readline()` 的未优化实现。

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

抽象基类 `RawIOBase` 是 `IOBase` 的子类。它负责将字节读取和写入流中。 `RawIOBase` 的子类 `FileIO` 提供计算机文件系统中文件的接口。

抽象基类 `BufferedIOBase` 继承了 `IOBase` ，处理原始二进制流（ `RawIOBase` ）上的缓冲。其子类 `BufferedWriter` 、 `BufferedReader` 和 `BufferedRWPair` 分别缓冲可读、可写以及可读写的原始二进制流。 `BufferedRandom` 提供了带缓冲的可随机访问流接口。 `BufferedIOBase` 的另一个子类 `BytesIO` 是内存中字节流。

抽象基类 `TextIOBase` 继承了 `IOBase` 。它处理可表示文本的流，并处理字符串的编码和解码。类 `TextIOWrapper` 继承了 `TextIOBase` ，是原始缓冲流（ `BufferedIOBase` ）的缓冲文本接口。最后， `StringIO` 是文本的内存流。

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

下表总结了抽象基类提供的 `io` 模块：

抽象基类 | 继承 | 抽象方法 | Mixin方法和属性
--- | --- | --- | ---
`IOBase` |  | `fileno`, `seek`, 和 `truncate` | `close`, `closed`, `__enter__`, `__exit__`, `flush`, `isatty`, `__iter__`, `__next__`, `readable`, `readline`, `readlines`, `seekable`, `tell`, `writable` 和 `writelines`
`RawIOBase` | `IOBase` | `readinto` 和 `write` | 继承 `IOBase` 方法, `read`, 和 `readall`
`BufferedIOBase` | `IOBase` | `detach`, `read`, `read1`, 和 `write` | 继承 `IOBase` 方法, `readinto`, 和 `readinto1`
`TextIOBase` | `IOBase` | `detach`, `read`, `readline`, 和 `write` | 继承 `IOBase` 方法, `encoding`, `errors`, 和 `newlines`

### I/O 基类

class `io.``IOBase`

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

  此类为许多方法提供了空的抽象实现，派生类可以有选择地重写。默认实现代表一个无法读取、写入或查找的文件。

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

  从文件读取或写入文件的二进制数据的基本类型为 `bytes` 。其他 bytes-like objects 也可以作为方法参数。文本I/O类使用 `str` 数据。

  请注意，在关闭的流上调用任何方法（甚至查询）都是未定义的（undefined）。在这种情况下，实现可能会引发 `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。

  `fileno`()

    返回流的底层文件描述符（整数）---如果存在。如果 IO 对象不使用文件描述符，则会引发 `OSError` 。

  `flush`()

    刷新流的写入缓冲区（如果适用）。这对只读和非阻塞流不起作用。

  `isatty`()

    如果流是交互式的（即连接到终端/tty设备），则返回 `True` 。

  `readable`()

    如果可以读取流，则返回 `True` 。否则为 `False` ，且 `read()` 将引发 `OSError` 错误。

  `readline`(size=-1)

    从流中读取并返回一行。如果指定了 size，将至多读取 size 个字节。

    对于二进制文件行结束符总是 `b'\n'`；对于文本文件，可以用将 newline 参数传给 `open()` 的方式来选择要识别的行结束符。

  `readlines`(hint=-1)

    从流中读取并返回包含多行的列表。可以指定 hint 来控制要读取的行数：如果（以字节/字符数表示的）所有行的总大小超出了 hint 则将不会读取更多的行。

    `0` 或更小的 hint 值以及 `None`，会被视为没有 hint。

    请注意使用 `for line in file: ...` 就足够对文件对象进行迭代了，可以不必调用 `file.readlines()`。

  `seek`(offset, whence=SEEK_SET)

    将流位置修改到给定的字节 offset。 offset 将相对于由 whence 指定的位置进行解析。 whence 的默认值为 `SEEK_SET`。 whence 的可用值有：

    - `SEEK_SET` 或 `0` -- 流的开头（默认值）；offset 应为零或正值

    - `SEEK_CUR` or `1` -- 当前流位置；offset 可以为负值

    - `SEEK_END` or `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)

    将行列表写入到流。 不会添加行分隔符，因此通常所提供的每一行都带有末尾行分隔符。

  `__del__`()

    为对象销毁进行准备。 `IOBase` 提供了此方法的默认实现，该实现会调用实例的 `close()` 方法。

class `io.``RawIOBase`

  原始二进制流的基类。 它继承自 `IOBase` 类。 没有公共构造器。

  原始二进制流通常会提供对下层 OS 设备或 API 的低层级访问，而不是尝试将其封装到高层级的基元中（此功能是在更高层级的缓冲二进制流和文本流中实现的，将在下文中描述）。

  `RawIOBase` 在 `IOBase` 的现有成员以外还提供了下列方法:

  `read`(size=-1)

    从对象中读取 size 个字节并将其返回。 作为一个便捷选项，如果 size 未指定或为 -1，则返回所有字节直到 EOF。 在其他情况下，仅会执行一次系统调用。 如果操作系统调用返回字节数少于 size 则此方法也可能返回少于 size 个字节。

    如果返回 0 个字节而 size 不为零 0，这表明到达文件末尾。 如果处于非阻塞模式并且没有更多字节可用，则返回 `None`。

    默认实现会转至 `readall()` 和 `readinto()`。

  `readall`()

    从流中读取并返回所有字节直到 EOF，如有必要将对流执行多次调用。

  `readinto`(b)

    将字节数据读入预先分配的可写 bytes-like object b，并返回所读取的字节数。 例如，b 可以是一个 `bytearray`。 如果对象处理非阻塞模式并且没有更多字节可用，则返回 `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)

    读取并返回最多 size 个字节。 如果此参数被省略、为 `None` 或为负值，则读取并返回所有数据直到 EOF。 如果流已经到达 EOF 则返回一个空的 `bytes` 对象。

    如果此参数为正值，并且下层原始流不可交互，则可能发起多个原始读取以满足字节计数（直至先遇到 EOF）。 但对于可交互原始流，则将至多发起一个原始读取，并且简短的结果并不意味着已到达 EOF。

    `BlockingIOError` 会在下层原始流不处于阻塞模式，并且当前没有可用数据时被引发。

  `read1`([size])

    通过至多一次对下层流的 `read()` (或 `readinto()`) 方法的调用读取并返回至多 size 个字节。 这适用于在 `BufferedIOBase` 对象之上实现你自己的缓冲区的情况。

    如果 size 为 `-1` (默认值)，则返回任意数量的字节（多于零字节，除非已到达 EOF）。

  `readinto`(b)

    将字节数据读入预先分配的可写 bytes-like object b 并返回所读取的字节数。 例如，b 可以是一个 `bytearray`。

    类似于 `read()`，可能对下层原始流发起多次读取，除非后者为交互式。

    `BlockingIOError` 会在下层原始流不处于阻塞模式，并且当前没有可用数据时被引发。

  `readinto1`(b)

    将字节数据读入预先分配的可写 bytes-like object b，其中至多使用一次对下层原始流 `read()` (或 `readinto()`) 方法的调用。 返回所读取的字节数。

    `BlockingIOError` 会在下层原始流不处于阻塞模式，并且当前没有可用数据时被引发。

    3.5 新版功能.

  `write`(b)

    写入给定的 bytes-like object b，并返回写入的字节数 (总是等于 b 的字节长度，因为如果写入失败则会引发 `OSError`)。 根据具体实现的不同，这些字节可能被实际写入下层流，或是出于运行效率和冗余等考虑而暂存于缓冲区。

    当处于非阻塞模式时，如果需要将数据写入原始流但它无法在不阻塞的情况下接受所有数据则将引发 `BlockingIOError`。

    调用者可能会在此方法返回后释放或改变 b，因此该实现应当仅在方法调用期间访问 b。

### 原始文件 I/O

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

  代表一个包含字节数据的 OS 层级文件的原始二进制流。 它继承自 `RawIOBase`。

  name 可以是以下两项之一：

  - 代表将被打开的文件路径的字符串或 `bytes` 对象。 在此情况下 closefd 必须为 `True` (默认值) 否则将会引发异常。

  - 代表一个现有 OS 层级文件描述符的号码的整数，作为结果的 `FileIO` 对象将可访问该文件。 当 FileIO 对象被关闭时此 fd 也将被关闭，除非 closefd 设为 `False`。

  mode 可以为 `'r'`, `'w'`, `'x'` 或 `'a'` 分别表示读取（默认模式）、写入、独占新建或添加。 如果以写入或添加模式打开的文件不存在将自动新建；当以写入模式打开时文件将先清空。 以新建模式打开时如果文件已存在则将引发 `FileExistsError`。 以新建模式打开文件也意味着要写入，因此该模式的行为与 `'w'` 类似。 在模式中附带 `'+'` 将允许同时读取和写入。

  该类的 `read()` (当附带正值参数调用时), `readinto()` 和 `write()` 方法将只执行一次系统调用。

  可以通过传入一个可调用对象作为 opener 来使用自定义文件打开器。 然后通过调用 opener 并传入 (name, flags) 来获取文件对象所对应的下层文件描述符。 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])

  一个使用内在字节缓冲区的二进制流。 它继承自 `BufferedIOBase`。 在 `close()` 方法被调用时将会丢弃缓冲区。

  可选参数 initial_bytes 是一个包含初始数据的 bytes-like object。

  `BytesIO` 在继承自 `BufferedIOBase` 和 `IOBase` 的成员以外还提供或重载了下列方法:

  `getbuffer`()

    返回一个对应于缓冲区内容的可读写视图而不必拷贝其数据。 此外，改变视图将透明地更新缓冲区内容:

        >>> b = io.BytesIO(b"abcdef")
        >>> view = b.getbuffer()
        >>> view[2:4] = b"56"
        >>> b.getvalue()
        b'ab56ef'

    注解

    只要视图保持存在，`BytesIO` 对象就无法被改变大小或关闭。

    3.2 新版功能.

  `getvalue`()

    返回包含整个缓冲区内容的 `bytes`。

  `read1`([size])

    在 `BytesIO` 中，这与 `read()` 相同。

    在 3.7 版更改: size 参数现在是可选的。

  `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`。

  `BufferedReader` 在继承自 `BufferedIOBase` 和 `IOBase` 的成员以外还提供或重载了下列方法:

  `peek`([size])

    从流返回字节数据而不前移位置。 完成此调用将至多读取一次原始流。 返回的字节数量可能少于或多于请求的数量。

  `read`([size])

    读取并返回 size 个字节，如果 size 未给定或为负值，则读取至 EOF 或是在非阻塞模式下读取调用将会阻塞。

  `read1`([size])

    在原始流上通过单次调用读取并返回至多 size 个字节。 如果至少缓冲了一个字节，则只返回缓冲的字节。 在其他情况下，将执行一次原始流读取。

    在 3.7 版更改: size 参数现在是可选的。

class `io.``BufferedWriter`(raw, buffer_size=DEFAULT_BUFFER_SIZE)

  一个提供对可写、不可查找的 `RawIOBase` 原始二进制流的高层级访问的缓冲二进制流。 它继承自 `BufferedIOBase`。

  当写入到此对象时，数据通常会被放入到内部缓冲区中。 缓冲区将在满足某些条件的情况下被写到下层的 `RawIOBase` 对象，包括:

  - 当缓冲区对于所有挂起数据而言太小时；

  - 当 `flush()` 被调用时

  - 当（为 `BufferedRandom` 对象）请求 `seek()` 时；

  - 当 `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)

  一个提供对不可查找的 `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 新版功能.

  `read`(size=-1)

    从流中读取至多 size 个字符并以单个 `str` 的形式返回。 如果 size 为负值或 `None`，则读取至 EOF。

  `readline`(size=-1)

    读取至换行符或 EOF 并返回单个 `str`。 如果流已经到达 EOF，则将返回一个空字符串。

    如果指定了 size ，最多将读取 size 个字符。

  `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.getpreferredencoding(False)`。

  errors 是一个可选的字符串，它指明编码格式和编码格式错误的处理方式。 传入 `'strict'` 将在出现编码格式错误时引发 `ValueError` (默认值 `None` 具有相同的效果)，传入 `'ignore'` 将忽略错误。 (请注意忽略编码格式错误会导致数据丢失。) `'replace'` 会在出现错误数据时插入一个替换标记 (例如 `'?'`)。 `'backslashreplace'` 将把错误数据替换为一个反斜杠转义序列。 在写入时，还可以使用 `'xmlcharrefreplace'` (替换为适当的 XML 字符引用) 或 `'namereplace'` (替换为 `\N{...}` 转义序列)。 任何其他通过 `codecs.register_error()` 注册的错误处理方式名称也可以被接受。

  newline 控制行结束符处理方式。 它可以为 `None`, `''`, `'\n'`, `'\r'` 和 `'\r\n'`。 其工作原理如下:

  - 当从流读取输入时，如果 newline 为 `None`，则将启用 universal newlines 模式。 输入中的行结束符可以为 `'\n'`, `'\r'` 或 `'\r\n'`，在返回给调用者之前它们会被统一转写为 `'\n'`。 如果 newline 为 `''`，也会启用通用换行模式，但行结束符会不加转写即返回给调用者。 如果 newline 具有任何其他合法的值，则输入行将仅由给定的字符串结束，并且行结束符会不加转写即返回给调用者。

  - 将输出写入流时，如果 newline 为 `None`，则写入的任何 `'\n'` 字符都将转换为系统默认行分隔符 `os.linesep`。如果 newline 是 `''` 或 `'\n'`，则不进行翻译。如果 newline 是任何其他合法值，则写入的任何 `'\n'` 字符将被转换为给定的字符串。

  如果 line_buffering 为 `True`，则当一个写入调用包含换行符或回车时将会应用 `flush()`。

  如果 write_through 为 `True`，对 `write()` 的调用会确保不被缓冲：在 `TextIOWrapper` 对象上写入的任何数据会立即交给其下层的 buffer 来处理。

  在 3.3 版更改: 已添加 write_through 参数

  在 3.3 版更改: 默认的 encoding 现在将为 `locale.getpreferredencoding(False)` 而非 `locale.getpreferredencoding()`。 不要使用 `locale.setlocale()` 来临时改变区域编码格式，要使用当前区域编码格式而不是用户的首选编码格式。

  `TextIOWrapper` 在继承自 `TextIOBase` 和 `IOBase` 的现有成员以外还提供了以下数据属性和方法:

  `line_buffering`

    是否启用行缓冲。

  `write_through`

    写入是否要立即传给下层的二进制缓冲。

    3.7 新版功能.

  `reconfigure`(*[, encoding][, errors][, newline][, line_buffering][, write_through])

    使用 encoding, errors, newline, line_buffering 和 write_through 的新设置来重新配置此文本流。

    未指定的形参将保留当前设定，例外情况是当指定了 encoding 但未指定 errors 时将会使用 `errors='strict'`。

    如果已经有数据从流中被读取则将无法再改变编码格式或行结束符。 另一方面，在写入数据之后再改变编码格式则是可以的。

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

    3.7 新版功能.

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

  一个使用内存文本缓冲的文本流。 它继承自 `TextIOBase`。

  当 `close()` 方法被调用时将会丢弃文本缓冲区。

  缓冲区的初始值可通过提供 initial_value 来设置。 如果启用了行结束符转写，换行将以 `write()` 所用的方式被编码。 数据流位置将被设为缓冲区的开头。

  newline 参数的规则与 `TextIOWrapper` 所用的一致，不同之处在于当将输出写入到流时，如果 newline 为 `None`，则在所有平台上换行符都会被写入为 `\n`。

  `StringIO` 在继承自 `TextIOBase` 和 `IOBase` 的现有成员以外还提供了以下方法:

  `getvalue`()

    返回一个包含缓冲区全部内容的 `str`。 换行符会以与 `read()` 相同的方式被编码，但是流的位置不会被改变。

  用法示例：

      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`。

## 性能

本节讨论所提供的具体 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和二进制数据之间进行转换。这在处理大量文本数据（如大型日志文件）时会变得非常明显。此外，由于使用的重构算法 `TextIOWrapper.tell()` 和 `TextIOWrapper.seek()` 都相当慢。

`StringIO` 是原生的内存 Unicode 容器，速度与 `BytesIO` 相似。

### 多线程

`FileIO` 对象是线程安全的，只要它们封装的操作系统调用（比如Unix下的 `read(2)` ）也是线程安全的。

二进制缓冲对象（例如 `BufferedReader`, `BufferedWriter`, `BufferedRandom` 和 `BufferedRWPair`）使用锁来保护其内部结构；因此，可以安全地一次从多个线程中调用它们。

`TextIOWrapper` 对象不再是线程安全的。

### 可重入性

二进制缓冲对象（ `BufferedReader` ， `BufferedWriter` ， `BufferedRandom` 和 `BufferedRWPair` 的实例）不是可重入的。虽然在正常情况下不会发生可重入调用，但仍可能会在 `signal` 处理程序执行 I/O 时产生。如果线程尝试重入已经访问的缓冲对象，则会引发 `RuntimeError` 。注意，这并不禁止其他线程进入缓冲对象。

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