"codecs" --- 编解码器注册和相关基类
***********************************

**源代码：** Lib/codecs.py

======================================================================

这个模块定义了标准 Python 编解码器（编码器和解码器）的基类并提供对内部
Python 编解码器注册表的访问，该注册表负责管理编解码器和错误处理的查找
过程。 大多数标准编解码器都属于 *文本编码格式*，它们可将文本编码为字节
串（以及将字节串解码为文本），但也提供了一些将文本编码为文本，以及将字
节串编码为字节串的编解码器。 自定义编解码器可以在任意类型间进行编码和
解码，但某些模块特性被限制为仅适用于 *文本编码格式* 或将数据编码为
"bytes" 的编解码器。

该模块定义了以下用于使用任何编解码器进行编码和解码的函数:

codecs.encode(obj, encoding='utf-8', errors='strict')

   使用为 *encoding* 注册的编解码器对 *obj* 进行编码。

   可以给定 *Errors* 以设置所需要的错误处理方案。 默认的错误处理方案
   "'strict'" 表示编码错误将引发 "ValueError" (或更特定编解码器相关的
   子类，例如 "UnicodeEncodeError")。 请参阅 编解码器基类 了解有关编解
   码器错误处理的更多信息。

codecs.decode(obj, encoding='utf-8', errors='strict')

   使用为 *encoding* 注册的编解码器对 *obj* 进行解码。

   可以给定 *Errors* 以设置所需要的错误处理方案。 默认的错误处理方案
   "'strict'" 表示解码错误将引发 "ValueError" (或更特定编解码器相关的
   子类，例如 "UnicodeDecodeError")。 请参阅 编解码器基类 了解有关编解
   码器错误处理的更多信息。

codecs.charmap_build(string)

   返回一个适用于以自定义单字节编码格式进行编码的映射。 给定一个表示解
   码表的至多 256 个字符的 "str" *string*，返回一个将字符序号映射到字
   节值的紧凑内部映射对象 "EncodingMap" 或 "字典"。 对于不合法的输入将
   引发 "TypeError"。

每种编解码器的完整细节也可以直接查找获取：

codecs.lookup(encoding, /)

   在 Python 编解码器注册表中查找编解码器信息，并返回一个 "CodecInfo"
   对象，其定义见下文。

   首先将会在注册表缓存中查找编码，如果未找到，则会扫描注册的搜索函数
   列表。 如果没有找到 "CodecInfo" 对象，则将引发 "LookupError"。 否则
   ，"CodecInfo" 对象将被存入缓存并返回给调用者。

class codecs.CodecInfo(encode, decode, streamreader=None, streamwriter=None, incrementalencoder=None, incrementaldecoder=None, name=None)

   查找编解码器注册表所得到的编解码器细节信息。 构造器参数将保存为同名
   的属性：

   name

      编码名称

   encode
   decode

      无状态的编码和解码函数。 它们必须是具有与 Codec 的 "encode()" 和
      "decode()" 方法相同接口的函数或方法 (参见 Codec 接口)。 这些函数
      或方法应当工作于无状态的模式。

   incrementalencoder
   incrementaldecoder

      增量式的编码器和解码器类或工厂函数。 这些函数必须分别提供由基类
      "IncrementalEncoder" 和 "IncrementalDecoder" 所定义的接口。 增量
      式编解码器可以保持状态。

   streamwriter
   streamreader

      流式写入器和读取器类或工厂函数。 这些函数必须分别提供由基类
      "StreamWriter" 和 "StreamReader" 所定义的接口。 流式编解码器可以
      保持状态。

为了简化对各种编解码器组件的访问，本模块提供了以下附加函数，它们使用
"lookup()" 来执行编解码器查找：

codecs.getencoder(encoding)

   查找给定编码的编解码器并返回其编码器函数。

   在编码无法找到时将引发 "LookupError"。

codecs.getdecoder(encoding)

   查找给定编码的编解码器并返回其解码器函数。

   在编码无法找到时将引发 "LookupError"。

codecs.getincrementalencoder(encoding)

   查找给定编码的编解码器并返回其增量式编码器类或工厂函数。

   在编码无法找到或编解码器不支持增量式编码器时将引发 "LookupError"。

codecs.getincrementaldecoder(encoding)

   查找给定编码的编解码器并返回其增量式解码器类或工厂函数。

   在编码无法找到或编解码器不支持增量式解码器时将引发 "LookupError"。

codecs.getreader(encoding)

   查找给定编码的编解码器并返回其 "StreamReader" 类或工厂函数。

   在编码无法找到时将引发 "LookupError"。

codecs.getwriter(encoding)

   查找给定编码的编解码器并返回其 "StreamWriter" 类或工厂函数。

   在编码无法找到时将引发 "LookupError"。

自定义编解码器的启用是通过注册适当的编解码器搜索函数：

codecs.register(search_function, /)

   注册一个编解码器搜索函数。 搜索函数预期接收一个参数，即全部以小写字
   母表示的编码格式名称，其中中连字符和空格会被转换为下划线，并返回一
   个 "CodecInfo" 对象。 在搜索函数无法找到给定编码格式的情况下，它应
   当返回 "None"。

   在 3.9 版本发生变更: 连字符和空格会被转换为下划线。

codecs.unregister(search_function, /)

   注销一个编解码器搜索函数并清空注册表缓存。 如果指定搜索函数未被注册
   ，则不做任何操作。

   Added in version 3.10.

虽然内置的 "open()" 和相关联的 "io" 模块是操作已编码文本文件的推荐方式
，但本模块也提供了额外的工具函数和类，允许在操作二进制文件时使用更多种
类的编解码器：

codecs.open(filename, mode='r', encoding=None, errors='strict', buffering=-1)

   使用给定的 *mode* 打开已编码的文件并返回一个 "StreamReaderWriter"
   的实例，提供透明的编码/解码。 默认的文件模式为 "'r'"，表示以读取模
   式打开文件。

   备注:

     如果 *encoding* 不为 "None"，则下层的已编码文件总是以二进制模式打
     开。 在读取和写入时不会自动执行 "'\n'" 的转换。 *mode* 参数可以是
     内置 "open()" 函数所接受的任意二进制模式；"'b'" 会被自动添加。

   *encoding* 指定文件所要使用的编码格式。 允许任何编码为字节串或从字
   节串解码的编码格式，而文件方法所支持的数据类型则取决于所使用的编解
   码器。

   可以指定 *errors* 来定义错误处理方案。 默认值 "'strict'" 表示在出现
   编码错误时引发 "ValueError"。

   *buffering* 的含义与内置 "open()" 函数中的相同。 默认值 -1 表示将使
   用默认的缓冲区大小。

   在 3.11 版本发生变更: "'U'" 模式已被移除。

   自 3.14 版本弃用: "codecs.open()" 已被 "open()" 取代。

codecs.EncodedFile(file, data_encoding, file_encoding=None, errors='strict')

   返回一个 "StreamRecoder" 实例，它提供了 *file* 的透明转码包装版本。
   当包装版本被关闭时原始文件也会被关闭。

   写入已包装文件的数据会根据给定的 *data_encoding* 解码，然后以使用
   *file_encoding* 的字节形式写入原始文件。 从原始文件读取的字节串将根
   据 *file_encoding* 解码，其结果将使用 *data_encoding* 进行编码。

   如果 *file_encoding* 未给定，则默认为 *data_encoding*。

   可以指定 *errors* 来定义错误处理方案。 默认值 "'strict'" 表示在出现
   编码错误时引发 "ValueError"。

codecs.iterencode(iterator, encoding, errors='strict', **kwargs)

   使用增量式编码器通过迭代来编码由 *iterator* 提供的输入。 *iterator*
   必须产生 "str" 对象。 此函数属于 *generator*。 *errors* 参数（以及
   任何其他关键字参数）会被传递给增量式编码器。

   此函数要求编解码器接受 "str" 对象形式的文本进行编码。 因此它不支持
   字节到字节的编码器，例如 "base64_codec"。

codecs.iterdecode(iterator, encoding, errors='strict', **kwargs)

   使用增量式解码器通过迭代来解码由 *iterator* 提供的输入。 *iterator*
   必须产生 "bytes" 对象。 此函数属于 *generator*。 *errors* 参数（以
   及任何其他关键字参数）会被传递给增量式解码器。

   此函数要求编解码器接受 "bytes" 对象进行解码。 因此它不支持文本到文
   本的编码器，例如 "rot_13"，但是 "rot_13" 可以通过同样效果的
   "iterencode()" 来使用。

codecs.readbuffer_encode(buffer, errors=None, /)

   返回一个包含 *buffer* 中原始字节数据的 "tuple"，一个 缓冲区兼容对象
   或 "str" (在处理前已编码为 UTF-8)，及其字节长度。

   *errors* 参数会被忽略。

      >>> codecs.readbuffer_encode(b"Zito")
      (b'Zito', 4)

本模块还提供了以下常量，适用于读取和写入依赖于平台的文件：

codecs.BOM
codecs.BOM_BE
codecs.BOM_LE
codecs.BOM_UTF8
codecs.BOM_UTF16
codecs.BOM_UTF16_BE
codecs.BOM_UTF16_LE
codecs.BOM_UTF32
codecs.BOM_UTF32_BE
codecs.BOM_UTF32_LE

   这些常量定义了多种字节序列，即一些编码格式的 Unicode 字节顺序标记（
   BOM）。 它们在 UTF-16 和 UTF-32 数据流中被用以指明所使用的字节顺序
   ，并在 UTF-8 中被用作 Unicode 签名。 "BOM_UTF16" 是 "BOM_UTF16_BE"
   或 "BOM_UTF16_LE"，具体取决于平台的本机字节顺序，"BOM" 是
   "BOM_UTF16" 的别名, "BOM_LE" 是 "BOM_UTF16_LE" 的别名，"BOM_BE" 是
   "BOM_UTF16_BE" 的别名。 其他序列则表示 UTF-8 和 UTF-32 编码格式中的
   BOM。


编解码器基类
============

The "codecs" module defines a set of base classes which define the
interfaces for working with codec objects, and can also be used as the
basis for custom codec implementations.

每种编解码器必须定义四个接口以便用作 Python 中的编解码器：无状态编码器
、无状态解码器、流读取器和流写入器。 流读取器和写入器通常会重用无状态
编码器/解码器来实现文件协议。 编解码器作者还需要定义编解码器将如何处理
编码和解码错误。


错误处理方案
------------

为了简化和标准化错误处理，编解码器可以通过接受 *errors* 字符串参数来实
现不同的错误处理方案:

>>> 'German ß, ♬'.encode(encoding='ascii', errors='backslashreplace')
b'German \\xdf, \\u266c'
>>> 'German ß, ♬'.encode(encoding='ascii', errors='xmlcharrefreplace')
b'German &#223;, &#9836;'

以下错误处理器可以用于所有的 Python 标准编码 编解码器:

+---------------------------+-------------------------------------------------+
| 值                        | 含意                                            |
|===========================|=================================================|
| "'strict'"                | 引发 "UnicodeError" (或其子类)，这是默认的方案  |
|                           | 。 在 "strict_errors()" 中实现。                |
+---------------------------+-------------------------------------------------+
| "'ignore'"                | 忽略错误格式的数据并且不加进一步通知就继续执行  |
|                           | 。 在 "ignore_errors()" 中实现。                |
+---------------------------+-------------------------------------------------+
| "'replace'"               | 用一个替代标记来替换。 在编码时，使用 "?"       |
|                           | (ASCII 字符)。 在解码时，使 用 "�" (U+FFFD，官  |
|                           | 方的 REPLACEMENT CHARACTER)。 在                |
|                           | "replace_errors()" 中实现。                     |
+---------------------------+-------------------------------------------------+
| "'backslashreplace'"      | 用反斜杠转义序列来替换。 在编码时，使用格式为   |
|                           | "\x*hh*" "\u*xxxx*" "\U*xxxxxxxx*" 的 Unicode   |
|                           | 码位十六进制表示形式。 在解码时，使用格式为     |
|                           | "\x*hh*" 的字节值十六进制表示形式。 在          |
|                           | "backslashreplace_errors()" 中 实现。           |
+---------------------------+-------------------------------------------------+
| "'surrogateescape'"       | 在解码时，将字节替换为 "U+DC80" 至 "U+DCFF" 范  |
|                           | 围内的单个代理代码。 当 在编码数据时使用        |
|                           | "'surrogateescape'" 错误处理方案时，此代理将被  |
|                           | 转换回 相同的字节。 （请参阅 **PEP 383** 了解详 |
|                           | 情。）                                          |
+---------------------------+-------------------------------------------------+

下列错误处理器仅在编码时适用（在 *文本编码格式* 类别以内）:

+---------------------------+-------------------------------------------------+
| 值                        | 含意                                            |
|===========================|=================================================|
| "'xmlcharrefreplace'"     | 用 XML/HTML 数字字符引用来替换，即格式为        |
|                           | "&#*num*;" 的 Unicode 码位十 进制表示形式。 在  |
|                           | "xmlcharrefreplace_errors()" 中实现。           |
+---------------------------+-------------------------------------------------+
| "'namereplace'"           | 用 "\N{...}" 转义序列来替换，出现在花括号中的是 |
|                           | 来自 Unicode 字符数据库 的 Name 属性。 在       |
|                           | "namereplace_errors()" 中实现。                 |
+---------------------------+-------------------------------------------------+

此外，以下错误处理方案被专门用于指定的编解码器：

+---------------------+--------------------------+---------------------------------------------+
| 值                  | 编解码器                 | 含意                                        |
|=====================|==========================|=============================================|
| "'surrogatepass'"   | utf-8, utf-16, utf-32,   | 允许将代理码位 ("U+D800" - "U+DFFF") 作为正 |
|                     | utf-16-be, utf-16-le,    | 常码位来编码和解码。 否则这 些编解码器会将  |
|                     | utf-32-be, utf-32-le     | "str" 中出现的代理码位视为错误。            |
+---------------------+--------------------------+---------------------------------------------+

Added in version 3.1: "'surrogateescape'" 和 "'surrogatepass'" 错误处
理方案。

在 3.4 版本发生变更: "'surrogatepass'" 错误处理器现在可适用于 utf-16*
和 utf-32* 编解码器。

Added in version 3.5: "'namereplace'" 错误处理方案。

在 3.5 版本发生变更: "'backslashreplace'" 错误处理器现在可适用于解码和
转码。

允许的值集合可以通过注册新命名的错误处理方案来扩展：

codecs.register_error(name, error_handler, /)

   在名称 *name* 之下注册错误处理函数 *error_handler*。 当 *name* 被指
   定为错误形参时，*error_handler* 参数所指定的对象将在编码和解码期间
   发生错误的情况下被调用，

   对于编码操作，将会调用 *error_handler* 并传入一个
   "UnicodeEncodeError" 实例，其中包含有关错误位置的信息。 错误处理程
   序必须引发此异常或别的异常，或者也可以返回一个元组，其中包含输入的
   不可编码部分的替换对象，以及应当继续进行编码的位置。 替换对象可以为
   "str" 或 "bytes" 类型。 如果替换对象为字节串，编码器将简单地将其复
   制到输出缓冲区。 如果替换对象为字符串，编码器将对替换对象进行编码。
   对原始输入的编码操作会在指定位置继续进行。 负的位置值将被视为相对于
   输入字符串的末尾。 如果结果位置超出范围则将引发 "IndexError"。

   解码和转换的做法很相似，不同之处在于将把 "UnicodeDecodeError" 或
   "UnicodeTranslateError" 传给处理程序，并且来自错误处理程序的替换对
   象将被直接放入输出。

之前注册的错误处理方案（包括标准错误处理方案）可通过名称进行查找：

codecs.lookup_error(name, /)

   返回之前在名称 *name* 之下注册的错误处理方案。

   在处理方案无法找到时将引发 "LookupError"。

以下标准错误处理方案也可通过模块层级函数的方式来使用：

codecs.strict_errors(exception)

   实现了 "'strict'" 错误处理。

   每个编码或解码错误都将引发 "UnicodeError"。

codecs.ignore_errors(exception)

   实现了 "'ignore'" 错误处理。

   错误格式的数据会被忽略；编码或解码将继续执行而不再通知。

codecs.replace_errors(exception)

   实现了 "'replace'" 错误处理。

   使用 "?" (ASCII 字符) 替换编码错误或者使用 "�" (U+FFFD，官方的
   REPLACEMENT CHARACTER) 替换解码错误。

codecs.backslashreplace_errors(exception)

   实现了 "'backslashreplace'" 错误处理。

   错误格式的数据会用反斜杠转义序列来替换。 在编码时，使用格式为
   "\x*hh*" "\u*xxxx*" "\U*xxxxxxxx*" 的 Unicode 码位十六进制表示形式
   。 在解码时，使用格式为 "\x*hh*" 的字节值 十六进制表示形式。

   在 3.5 版本发生变更: 适用于解码和转码。

codecs.xmlcharrefreplace_errors(exception)

   实现 "'xmlcharrefreplace'" 错误处理（仅限 *text encoding* 范围内的
   编码操作）。

   不可编码的字符会被替换为适当的 XML/HTML 数值字符引用，即格式为
   "&#*num*;" 的十进制形式 Unicode 码位。

codecs.namereplace_errors(exception)

   实现 "'namereplace'" 错误处理（仅限 *text encoding* 范围内的编码操
   作）。

   不可编码的字符会被替换为 "\N{...}" 转义序列。 出现在花括号内的字符
   集合是来自于 Unicode 字符数据库的 Name 属性。 例如，德语小写字母
   "'ß'" 将被转换为字符序列 "\N{LATIN SMALL LETTER SHARP S}"。

   Added in version 3.5.


无状态的编码和解码
------------------

基本 "Codec" 类定义了这些方法，同时还定义了无状态编码器和解码器的函数
接口：

class codecs.Codec

   encode(input, errors='strict')

      编码 *input* 对象并返回一个元组 (输出对象, 消耗长度)。 例如，
      *text encoding* 会使用特定的字符集编码格式 (例如 "cp1252" 或
      "iso-8859-1") 将字符串转换为字节串对象。

      *errors* 参数定义了要应用的错误处理方案。 默认为 "'strict'" 处理
      方案。

      此方法不一定会在 "Codec" 实例中保存状态。 可使用必须保存状态的
      "StreamWriter" 作为编解码器以便高效地进行编码。

      编码器必须能够处理零长度的输入并在此情况下返回输出对象类型的空对
      象。

   decode(input, errors='strict')

      解码 *input* 对象并返回一个元组 (输出对象, 消耗长度)。 例如，
      *text encoding* 的解码操作会使用特定的字符集编码格式将字节串对象
      转换为字符串对象。

      对于文本编码格式和字节到字节编解码器，*input* 必须为一个字节串对
      象或提供了只读缓冲区接口的对象 -- 例如，缓冲区对象和映射到内存的
      文件。

      *errors* 参数定义了要应用的错误处理方案。 默认为 "'strict'" 处理
      方案。

      此方法不一定会在 "Codec" 实例中保存状态。 可使用必须保存状态的
      "StreamReader" 作为编解码器以便高效地进行解码。

      解码器必须能够处理零长度的输入并在此情况下返回输出对象类型的空对
      象。


增量式的编码和解码
------------------

"IncrementalEncoder" 和 "IncrementalDecoder" 类提供了增量式编码和解码
的基本接口。 对输入的编码/解码不是通过对无状态编码器/解码器的一次调用
，而是通过对增量式编码器/解码器的 "encode()"/"decode()" 方法的多次调用
。 增量式编码器/解码器会在方法调用期间跟踪编码/解码过程。

调用 "encode()"/"decode()" 方法后的全部输出相当于将所有通过无状态编码
器/解码器进行编码/解码的单个输入连接在一起所得到的输出。


IncrementalEncoder 对象
~~~~~~~~~~~~~~~~~~~~~~~

"IncrementalEncoder" 类用来对一个输入进行分步编码。 它定义了以下方法，
每个增量式编码器都必须定义这些方法以便与 Python 编解码器注册表相兼容。

class codecs.IncrementalEncoder(errors='strict')

   "IncrementalEncoder" 实例的构造器。

   所有增量式编码器必须提供此构造器接口。 它们可以自由地添加额外的关键
   字参数，但只有在这里定义的参数才会被 Python 编解码器注册表所使用。

   "IncrementalEncoder" 可以通过提供 *errors* 关键字参数来实现不同的错
   误处理方案。 可用的值请参阅 错误处理方案。

   *errors* 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在
   "IncrementalEncoder" 对象的生命期内在不同的错误处理策略之间进行切换
   。

   encode(object, final=False)

      编码 *object* (会将编码器的当前状态纳入考虑) 并返回已编码的结果
      对象。 如果这是对 "encode()" 的最终调用则 *final* 必须为真值（默
      认为假值）。

   reset()

      将编码器重置为初始状态。 输出将被丢弃：调用 ".encode(object,
      final=True)"，在必要时传入一个空字节串或字符串，重置编码器并得到
      输出。

   getstate()

      返回编码器的当前状态，该值必须为一个整数。 实现应当确保 "0" 是最
      常见的状态。 （比整数更复杂的状态表示可以通过编组/选择状态并将结
      果字符串的字节数据编码为整数来转换为一个整数值）。

   setstate(state)

      将编码器的状态设为 *state*。 *state* 必须为 "getstate()" 所返回
      的一个编码器状态。


IncrementalDecoder 对象
~~~~~~~~~~~~~~~~~~~~~~~

"IncrementalDecoder" 类用来对一个输入进行分步解码。 它定义了以下方法，
每个增量式解码器都必须定义这些方法以便与 Python 编解码器注册表相兼容。

class codecs.IncrementalDecoder(errors='strict')

   "IncrementalDecoder" 实例的构造器。

   所有增量式解码器必须提供此构造器接口。 它们可以自由地添加额外的关键
   字参数，但只有在这里定义的参数才会被 Python 编解码器注册表所使用。

   "IncrementalDecoder" 可以通过提供 *errors* 关键字参数来实现不同的错
   误处理方案。 可用的值请参阅 错误处理方案。

   *errors* 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在
   "IncrementalDecoder" 对象的生命期内在不同的错误处理策略之间进行切换
   。

   decode(object, final=False)

      解码 *object* (会将解码器的当前状态纳入考虑) 并返回已解码的结果
      对象。 如果这是对 "decode()" 的最终调用则 *final* 必须为真值（默
      认为假值）。 如果 *final* 为真值则解码器必须对输入进行完全解码并
      且必须 刷新所有缓冲区。 如果这无法做到（例如由于在输入结束时字节
      串序列不完整）则它必须像在无状态的情况下那样初始化错误处理（这可
      能引发一个异常）。

   reset()

      将解码器重置为初始状态。

   getstate()

      返回解码器的当前状态。 这必须为一个二元组，第一项必须是包含尚未
      解码的输入的缓冲区。 第二项必须为一个整数，可以表示附加状态信息
      。 （实现应当确保 "0" 是最常见的附加状态信息。） 如果此附加状态
      信息为 "0" 则必须可以将解码器设为没有已缓冲输入并且以 "0" 作为附
      加状态信息，以便将先前已缓冲的输入馈送到解码器使其返回到先前的状
      态而不产生任何输出。 （比整数更复杂的附加状态信息可以通过编组/选
      择状态信息并将结果字符串的字节数据编码为整数来转换为一个整数值。
      ）

   setstate(state)

      将解码器的状态设为 *state*。 *state* 必须为 "getstate()" 所返回
      的一个解码器状态。


流式的编码和解码
----------------

"StreamWriter" 和 "StreamReader" 类提供了一些泛用工作接口，可被用来非
常方便地实现新的编码格式子模块。 请参阅 "encodings.utf_8" 中的示例了解
如何做到这一点。


StreamWriter 对象
~~~~~~~~~~~~~~~~~

"StreamWriter" 类是 "Codec" 的子类，它定义了以下方法，每个流式写入器都
必须定义这些方法以便与 Python 编解码器注册表相兼容。

class codecs.StreamWriter(stream, errors='strict')

   "StreamWriter" 实例的构造器。

   所有流式写入器必须提供此构造器接口。 它们可以自由地添加额外的关键字
   参数，但只有在这里定义的参数才会被 Python 编解码器注册表所使用。

   *stream* 参数必须为一个基于特定编解码器打开用于写入文本或二进制数据
   的文件型对象。

   "StreamWriter" 可以通过提供 *errors* 关键字参数来实现不同的错误处理
   方案。 请参阅 错误处理方案 了解下层的流式编解码器可支持的标准错误处
   理方案。

   *errors* 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在
   "StreamWriter" 对象的生命期内在不同的错误处理策略之间进行切换。

   write(object)

      将编码后的对象内容写入到流。

   writelines(list)

      将拼接后的字符串可迭代对象写入到流（可能通过重用 "write()" 方法
      ）。 无限长或非常大的可迭代对象不受支持。 标准的字节到字节编解码
      器不支持此方法。

   reset()

      重置用于保持内部状态的编解码器缓冲区。

      调用此方法应当确保在干净的状态下放入输出数据，以允许直接添加新的
      干净数据而无须重新扫描整个流来恢复状态。

除了上述的方法，"StreamWriter" 还必须继承来自下层流的所有其他方法和属
性。


StreamReader 对象
~~~~~~~~~~~~~~~~~

"StreamReader" 类是 "Codec" 的子类，它定义了以下方法，每个流式读取器都
必须定义这些方法以便与 Python 编解码器注册表相兼容。

class codecs.StreamReader(stream, errors='strict')

   "StreamReader" 实例的构造器。

   所有流式读取器必须提供此构造器接口。 它们可以自由地添加额外的关键字
   参数，但只有在这里定义的参数才会被 Python 编解码器注册表所使用。

   *stream* 参数必须为一个基于特定编解码器打开用于读取文本或二进制数据
   的文件型对象。

   "StreamReader" 可以通过提供 *errors* 关键字参数来实现不同的错误处理
   方案。 请参阅 错误处理方案 了解下层的流式编解码器可支持的标准错误处
   理方案。

   *errors* 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在
   "StreamReader" 对象的生命期内在不同的错误处理策略之间进行切换。

   *errors* 参数所允许的值集合可以使用 "register_error()" 来扩展。

   read(size=-1, chars=-1, firstline=False)

      解码来自流的数据并返回结果对象。

      *chars* 参数指明要返回的解码后码位或字节数量。 "read()" 方法绝不
      会返回超出请求数量的数据，但如果可用数量不足，它可能返回少于请求
      数量的数据。

      *size* 参数指明要读取并解码的已编码字节或码位的最大数量近似值。
      解码器可以适当地修改此设置。 默认值 -1 表示尽可能多地读取并解码
      。 此形参的目的是防止一次性解码过于巨大的文件。

      *firstline* 旗标指明如果在后续行发生解码错误，则仅返回第一行就足
      够了。

      此方法应当使用“贪婪”读取策略，这意味着它应当在编码格式定义和给定
      大小所允许的情况下尽可能多地读取数据，例如，如果在流上存在可选的
      编码结束或状态标记，这些内容也应当被读取。

   readline(size=None, keepends=True)

      从输入流读取一行并返回解码后的数据。

      如果给定了 *size*，则将其作为 size 参数传递给流的 "read()" 方法
      。

      如果 *keepends* 为假值，则行结束符将从返回的行中去除。

   readlines(sizehint=None, keepends=True)

      从输入流读取所有行并将其作为一个行列表返回。

      行结束符会使用编解码器的 "decode()" 方法来实现，并且如果
      *keepends* 为真值则会将其包含在列表条目中。

      如果给定了 *sizehint*，则将其作为 *size* 参数传递给流的 "read()"
      方法。

   reset()

      重置用于保持内部状态的编解码器缓冲区。

      请注意不应当对流进行重定位。 使用此方法的主要目的是为了能够从解
      码错误中恢复。

除了上述的方法，"StreamReader" 还必须继承来自下层流的所有其他方法和属
性。


StreamReaderWriter 对象
~~~~~~~~~~~~~~~~~~~~~~~

"StreamReaderWriter" 是一个方便的类，允许对同时工作于读取和写入模式的
流进行包装。

其设计使得开发者可以使用 "lookup()" 函数所返回的工厂函数来构造实例。

class codecs.StreamReaderWriter(stream, Reader, Writer, errors='strict')

   创建一个 "StreamReaderWriter" 实例。 *stream* 必须为一个文件型对象
   。 *Reader* 和 *Writer* 必须为分别提供了 "StreamReader" 和
   "StreamWriter" 接口的工厂函数或类。 错误处理通过与流式读取器和写入
   器所定义的相同方式来完成。

"StreamReaderWriter" 实例定义了 "StreamReader" 和 "StreamWriter" 类的
组合接口。 它们还继承了来自下层流的所有其他方法和属性。


StreamRecoder 对象
~~~~~~~~~~~~~~~~~~

"StreamRecoder" 将数据从一种编码格式转换为另一种，这对于处理不同编码环
境的情况有时会很有用。

其设计使得开发者可以使用 "lookup()" 函数所返回的工厂函数来构造实例。

class codecs.StreamRecoder(stream, encode, decode, Reader, Writer, errors='strict')

   创建一个实现了双向转换的 "StreamRecoder" 实例: *encode* 和 *decode*
   工作于前端 —— 调用 "read()" 和 "write()" 的代码可见的数据，而
   *Reader* 和 *Writer* 工作于后端 —— *stream* 中的数据。

   你可以使用这些对象来进行透明转码，例如从 Latin-1 转为 UTF-8 以及反
   向转换。

   *stream* 参数必须为一个文件型对象。

   *encode* 和 *decode* 参数必须遵循 "Codec" 接口。 *Reader* 和
   *Writer* 必须为分别提供了 "StreamReader" 和 "StreamWriter" 接口对象
   的工厂函数或类。

   错误处理通过与流式读取器和写入器所定义的相同方式来完成。

"StreamRecoder" 实例定义了 "StreamReader" 和 "StreamWriter" 类的组合接
口。 它们还继承了来自下层流的所有其他方法和属性。


编码格式与 Unicode
==================

字符串在系统内部存储为 "U+0000"--"U+10FFFF" 范围内的码位序列。 （请参
阅 **PEP 393** 了解有关实现的详情。） 一旦字符串对象要在 CPU 和内存以
外使用，字节的大小端顺序和字节数组的存储方式就成为一个影响因素。 如同
使用其他编解码器一样，将字符串序列化为字节序列被称为 *编码*，而从字节
序列重建字符串被称为 *解码*。 存在许多不同的文本序列化编解码器，它们被
统称为 *文本编码格式*。

最简单的文本编码格式 (称为 "'latin-1'" 或 "'iso-8859-1'") 将码位 0--
255 映射为字节值 "0x0"--"0xff"，这意味着包含 "U+00FF" 以上码位的字符串
对象无法使用此编解码器进行编码。 这样做将引发 "UnicodeEncodeError"，其
形式类似下面这样（不过详细的错误信息可能会有所不同）:
"UnicodeEncodeError: 'latin-1' codec can't encode character '\u1234'
in position 3: ordinal not in range(256)"。

还有另外一组编码格式（所谓的字符映射编码）会选择全部 Unicode 码位的不
同子集并设定如何将这些码位映射为字节值 "0x0"--"0xff"。 要查看这是如何
实现的，只需简单地打开相应源码例如 "encodings/cp1252.py" (这是一个主要
在 Windows 上使用的编码格式)。 其中会有一个包含 256 个字符的字符串常量
，指明每个字符所映射的字节值。

所有这些编码格式只能编码在 Unicode 中定义的 1114112 个码位中的 256 个
。 一种能够存储每个 Unicode 码位的简单直观的做法就是将每个码位存储为四
个连续的字节。 这有两种可能的方式：以大端序或小端序存储字节。 这两种编
码格式分别被称为 "UTF-32-BE" 和 "UTF-32-LE"。 它们是有缺点的，举例来说
，如果你在小端序的机器上使用 "UTF-32-BE" 你就必须在编码和解码时交换字
节顺序。 Python 的 "UTF-16" 和 "UTF-32" 编解码器会在没有 BOM 时通过使
用平台的原生字节序来避免这个问题。 Python 会遵循主流平台的最佳实践，这
样原生字节序的数据在处理时就没有冗余的字节交换，即使 Unicode 标准在未
指明字节序时默认使用大端序。 当 CPU 以不同的字节序读取字节数据时，必须
进行字节交换。 为了能够检测 "UTF-16" 或 "UTF-32" 字节序列的字节序，可
以使用 BOM ("Byte Order Mark")。 对应 Unicode 字符 "U+FEFF"。 此字符可
被添加到每个 "UTF-16" 或 "UTF-32" 字节序列之前。此字符的交换字节版本
("0xFFFE") 是不可在 Unicode 文本中出现的非法字符。 当一个 "UTF-16" 或
"UTF-32" 的首字符为 "U+FFFE" 时，该字节数据就必须在解码时交换字节序。

不幸的是字符 "U+FEFF" 还有另一个作为 "ZERO WIDTH NO-BREAK SPACE" 的含
义：表示没有宽度且不允许拆分单词的字符。 例如它可被用于对连字算法进行
提示。 在 Unicode 4.0 中 "U+FEFF" 作为 "ZERO WIDTH NO-BREAK SPACE" 的
含义已被弃用 (使用 "U+2060" ("WORD JOINER") 担任此任务)。 不过 Unicode
软件仍然必须能够在两种任务下处理 "U+FEFF": 作为 BOM 它是确定已编码字节
串的存储布局的标记，并会在字节序列被解码为字符串时消失；作为 "ZERO
WIDTH NO-BREAK SPACE" 它是会如任何其他字符一样被解码的普通字符。

还有另一种编码格式能够对所有 Unicode 字符进行编码：UTF-8。 UTF-8 是一
种 8 位编码，这意味着在 UTF-8 中没有字节顺序问题。 UTF-8 字节序列中的
每个字节由两部分组成：标志位（最重要的位）和内容位。 标志位是由零至四
个值为 "1" 的二进制位加一个值为 "0" 的二进制位构成的序列。 Unicode 字
符会按以下形式进行编码（其中 x 为内容位，当拼接为一体时将给出对应的
Unicode 字符）:

+-------------------------------------+------------------------------------------------+
| 范围                                | 编码                                           |
|=====================================|================================================|
| "U-00000000" ... "U-0000007F"       | 0xxxxxxx                                       |
+-------------------------------------+------------------------------------------------+
| "U-00000080" ... "U-000007FF"       | 110xxxxx 10xxxxxx                              |
+-------------------------------------+------------------------------------------------+
| "U-00000800" ... "U-0000FFFF"       | 1110xxxx 10xxxxxx 10xxxxxx                     |
+-------------------------------------+------------------------------------------------+
| "U-00010000" ... "U-0010FFFF"       | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx            |
+-------------------------------------+------------------------------------------------+

Unicode 字符最不重要的一个位就是最右侧的二进制位 x。

由于 UTF-8 是一种 8 位编码格式，因此 BOM 是不必要的，并且已编码字符串
中的任何 "U+FEFF" 字符（即使是作为第一个字符）都会被视为是 "ZERO WIDTH
NO-BREAK SPACE"。

在没有外部信息的情况下将不可能毫无疑义地确定一个字符串使用了何种编码格
式。 每种字符映射编码格式都可以解码任意的随机字节序列。 然而对 UTF-8
来说这却是不可能的，因为 UTF-8 字节序列具有不允许任意字节序列的特别结
构。 为了提升 UTF-8 编码格式检测的可靠性，Microsoft 发明了一种 UTF-8
的变体形式 (Python 称之为 ""utf-8-sig"") 专门用于其 Notepad 程序：在任
何 Unicode 字节被写入文件之前，会先写入一个 UTF-8 编码的 BOM (它看起来
是这样一个字节序列: "0xef", "0xbb", "0xbf")。 由于任何字符映射编码后的
文件都不大可能以这些字节值开头 (例如它们会映射为

      LATIN SMALL LETTER I WITH DIAERESIS
      RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
      INVERTED QUESTION MARK

对于 iso-8859-1 编码格式来说），这提升了根据字节序列来正确猜测
"utf-8-sig" 编码格式的成功率。 所以在这里 BOM 的作用并不是帮助确定生成
字节序列所使用的字节顺序，而是作为帮助猜测编码格式的记号。 在进行编码
时 utf-8-sig 编解码器将把 "0xef", "0xbb", "0xbf" 作为头三个字节写入文
件。 在进行解码时 "utf-8-sig" 将跳过这三个字节，如果它们作为文件的头三
个字节出现的话。 在 UTF-8 中并不推荐使用 BOM，通常应当避免它们的出现。


标准编码
========

Python 内置了多种编解码器，这些编解码器既可以通过 C 函数实现，也可以使
用字典作为映射表来实现。下表按名称列出了这些编解码器，同时提供了部分常
用别名以及该编码格式可能适用的语言。需要注意的是，所列的别名列表和语言
列表并非详尽无遗。此外，请注意，仅存在大小写差异或使用连字符替代下划线
的拼写变体同样属于有效别名，因为在经过 "normalize_encoding()" 规范化处
理后，这些形式是等效的。例如，"'utf-8'" 就是 "'utf_8'" 编解码器的一个
有效别名。

备注:

  下表列出了最常见的编解码器别名，如需查看完整列表，请参阅源文件
  aliases.py。

在 Windows 系统上，"cpXXX" 编解码器可用于所有代码页。 但只有下表中列出
的编解码器才能保证在其他平台上存在。

有些常见编码格式可以绕过编解码器查找机制来提升性能。 这些优化机会对于
CPython 来说仅能通过一组有限的别名（大小写不敏感）来识别：utf-8, utf8,
latin-1, latin1, iso-8859-1, iso8859-1, mbcs (Windows 专属), ascii,
us-ascii, utf-16, utf16, utf-32, utf32, 也包括使用下划线替代连字符的的
形式。 使用这些编码格式的其他别名可能会导致更慢的执行速度。

在 3.6 版本发生变更: 可识别针对 us-ascii 的优化机会。

许多字符集都支持相同的语言。 它们在个别字符（例如是否支持 EURO SIGN 等
）以及给字符所分配的码位方面存在差异。 特别是对于欧洲语言来说，通常存
在以下几种变体：

* 某个 ISO 8859 编码集

* 某个 Microsoft Windows 编码页，通常是派生自某个 8859 编码集，但会用
  附加的图形字符来替换控制字符。

* 某个 IBM EBCDIC 编码页

* 某个 IBM PC 编码页，通常会兼容 ASCII

+-------------------+----------------------------------+----------------------------------+
| 编码              | 别名                             | 语言                             |
|===================|==================================|==================================|
| ascii             | 646, us-ascii                    | 英语                             |
+-------------------+----------------------------------+----------------------------------+
| big5              | big5-tw, csbig5                  | 繁体中文                         |
+-------------------+----------------------------------+----------------------------------+
| big5hkscs         | big5-hkscs, hkscs                | 繁体中文                         |
+-------------------+----------------------------------+----------------------------------+
| cp037             | IBM037, IBM039                   | 英语                             |
+-------------------+----------------------------------+----------------------------------+
| cp273             | 273, IBM273, csIBM273            | 德语  Added in version 3.4.      |
+-------------------+----------------------------------+----------------------------------+
| cp424             | EBCDIC-CP-HE, IBM424             | 希伯来语                         |
+-------------------+----------------------------------+----------------------------------+
| cp437             | 437, IBM437                      | 英语                             |
+-------------------+----------------------------------+----------------------------------+
| cp500             | EBCDIC-CP-BE, EBCDIC-CP-CH,      | 西欧                             |
|                   | IBM500                           |                                  |
+-------------------+----------------------------------+----------------------------------+
| cp720             |                                  | 阿拉伯语                         |
+-------------------+----------------------------------+----------------------------------+
| cp737             |                                  | 希腊语                           |
+-------------------+----------------------------------+----------------------------------+
| cp775             | IBM775                           | 波罗的海语言                     |
+-------------------+----------------------------------+----------------------------------+
| cp850             | 850, IBM850                      | 西欧                             |
+-------------------+----------------------------------+----------------------------------+
| cp852             | 852, IBM852                      | 中欧和东欧                       |
+-------------------+----------------------------------+----------------------------------+
| cp855             | 855, IBM855                      | 白俄罗斯语，保加利亚语，马其顿语 |
|                   |                                  | ，俄语，塞尔维亚语               |
+-------------------+----------------------------------+----------------------------------+
| cp856             |                                  | 希伯来语                         |
+-------------------+----------------------------------+----------------------------------+
| cp857             | 857, IBM857                      | 土耳其语                         |
+-------------------+----------------------------------+----------------------------------+
| cp858             | 858, IBM858                      | 西欧                             |
+-------------------+----------------------------------+----------------------------------+
| cp860             | 860, IBM860                      | 葡萄牙语                         |
+-------------------+----------------------------------+----------------------------------+
| cp861             | 861, CP-IS, IBM861               | 冰岛语                           |
+-------------------+----------------------------------+----------------------------------+
| cp862             | 862, IBM862                      | 希伯来语                         |
+-------------------+----------------------------------+----------------------------------+
| cp863             | 863, IBM863                      | 加拿大语                         |
+-------------------+----------------------------------+----------------------------------+
| cp864             | IBM864                           | 阿拉伯语                         |
+-------------------+----------------------------------+----------------------------------+
| cp865             | 865, IBM865                      | 丹麦语/挪威语                    |
+-------------------+----------------------------------+----------------------------------+
| cp866             | 866, IBM866                      | 俄语                             |
+-------------------+----------------------------------+----------------------------------+
| cp869             | 869, CP-GR, IBM869               | 希腊语                           |
+-------------------+----------------------------------+----------------------------------+
| cp874             |                                  | 泰语                             |
+-------------------+----------------------------------+----------------------------------+
| cp875             |                                  | 希腊语                           |
+-------------------+----------------------------------+----------------------------------+
| cp932             | 932, ms932, mskanji, ms-kanji,   | 日语                             |
|                   | windows-31j                      |                                  |
+-------------------+----------------------------------+----------------------------------+
| cp949             | 949, ms949, uhc                  | 韩语                             |
+-------------------+----------------------------------+----------------------------------+
| cp950             | 950, ms950                       | 繁体中文                         |
+-------------------+----------------------------------+----------------------------------+
| cp1006            |                                  | 乌尔都语                         |
+-------------------+----------------------------------+----------------------------------+
| cp1026            | ibm1026                          | 土耳其语                         |
+-------------------+----------------------------------+----------------------------------+
| cp1125            | 1125, ibm1125, cp866u, ruscii    | 乌克兰语  Added in version 3.4.  |
+-------------------+----------------------------------+----------------------------------+
| cp1140            | ibm1140                          | 西欧                             |
+-------------------+----------------------------------+----------------------------------+
| cp1250            | windows-1250                     | 中欧和东欧                       |
+-------------------+----------------------------------+----------------------------------+
| cp1251            | windows-1251                     | 白俄罗斯语，保加利亚语，马其顿语 |
|                   |                                  | ，俄语，塞尔维亚语               |
+-------------------+----------------------------------+----------------------------------+
| cp1252            | windows-1252                     | 西欧                             |
+-------------------+----------------------------------+----------------------------------+
| cp1253            | windows-1253                     | 希腊语                           |
+-------------------+----------------------------------+----------------------------------+
| cp1254            | windows-1254                     | 土耳其语                         |
+-------------------+----------------------------------+----------------------------------+
| cp1255            | windows-1255                     | 希伯来语                         |
+-------------------+----------------------------------+----------------------------------+
| cp1256            | windows-1256                     | 阿拉伯语                         |
+-------------------+----------------------------------+----------------------------------+
| cp1257            | windows-1257                     | 波罗的海语言                     |
+-------------------+----------------------------------+----------------------------------+
| cp1258            | windows-1258                     | 越南语                           |
+-------------------+----------------------------------+----------------------------------+
| euc_jp            | eucjp, ujis, u-jis               | 日语                             |
+-------------------+----------------------------------+----------------------------------+
| euc_jis_2004      | jisx0213, eucjis2004             | 日语                             |
+-------------------+----------------------------------+----------------------------------+
| euc_jisx0213      | eucjisx0213                      | 日语                             |
+-------------------+----------------------------------+----------------------------------+
| euc_kr            | euckr, korean, ksc5601,          | 韩语                             |
|                   | ks_c-5601, ks_c-5601-1987,       |                                  |
|                   | ksx1001, ks_x-1001               |                                  |
+-------------------+----------------------------------+----------------------------------+
| gb2312            | chinese, csiso58gb231280, euc-   | 简体中文                         |
|                   | cn, euccn, eucgb2312-cn,         |                                  |
|                   | gb2312-1980, gb2312-80, iso-     |                                  |
|                   | ir-58                            |                                  |
+-------------------+----------------------------------+----------------------------------+
| gbk               | 936, cp936, ms936                | 统一汉语                         |
+-------------------+----------------------------------+----------------------------------+
| gb18030           | gb18030-2000                     | 统一汉语                         |
+-------------------+----------------------------------+----------------------------------+
| hz                | hzgb, hz-gb, hz-gb-2312          | 简体中文                         |
+-------------------+----------------------------------+----------------------------------+
| iso2022_jp        | csiso2022jp, iso2022jp,          | 日语                             |
|                   | iso-2022-jp                      |                                  |
+-------------------+----------------------------------+----------------------------------+
| iso2022_jp_1      | iso2022jp-1, iso-2022-jp-1       | 日语                             |
+-------------------+----------------------------------+----------------------------------+
| iso2022_jp_2      | iso2022jp-2, iso-2022-jp-2       | 日语，韩语，简体中文，西欧，希腊 |
|                   |                                  | 语                               |
+-------------------+----------------------------------+----------------------------------+
| iso2022_jp_2004   | iso2022jp-2004, iso-2022-jp-2004 | 日语                             |
+-------------------+----------------------------------+----------------------------------+
| iso2022_jp_3      | iso2022jp-3, iso-2022-jp-3       | 日语                             |
+-------------------+----------------------------------+----------------------------------+
| iso2022_jp_ext    | iso2022jp-ext, iso-2022-jp-ext   | 日语                             |
+-------------------+----------------------------------+----------------------------------+
| iso2022_kr        | csiso2022kr, iso2022kr,          | 韩语                             |
|                   | iso-2022-kr                      |                                  |
+-------------------+----------------------------------+----------------------------------+
| latin_1           | iso-8859-1, iso8859-1, 8859,     | 西欧                             |
|                   | cp819, latin, latin1, L1         |                                  |
+-------------------+----------------------------------+----------------------------------+
| iso8859_2         | iso-8859-2, latin2, L2           | 中欧和东欧                       |
+-------------------+----------------------------------+----------------------------------+
| iso8859_3         | iso-8859-3, latin3, L3           | 世界语，马耳他语                 |
+-------------------+----------------------------------+----------------------------------+
| iso8859_4         | iso-8859-4, latin4, L4           | 北欧                             |
+-------------------+----------------------------------+----------------------------------+
| iso8859_5         | iso-8859-5, cyrillic             | 白俄罗斯语，保加利亚语，马其顿语 |
|                   |                                  | ，俄语，塞尔维亚语               |
+-------------------+----------------------------------+----------------------------------+
| iso8859_6         | iso-8859-6, arabic               | 阿拉伯语                         |
+-------------------+----------------------------------+----------------------------------+
| iso8859_7         | iso-8859-7, greek, greek8        | 希腊语                           |
+-------------------+----------------------------------+----------------------------------+
| iso8859_8         | iso-8859-8, hebrew               | 希伯来语                         |
+-------------------+----------------------------------+----------------------------------+
| iso8859_9         | iso-8859-9, latin5, L5           | 土耳其语                         |
+-------------------+----------------------------------+----------------------------------+
| iso8859_10        | iso-8859-10, latin6, L6          | 北欧语言                         |
+-------------------+----------------------------------+----------------------------------+
| iso8859_11        | iso-8859-11, thai                | 泰语                             |
+-------------------+----------------------------------+----------------------------------+
| iso8859_13        | iso-8859-13, latin7, L7          | 波罗的海语言                     |
+-------------------+----------------------------------+----------------------------------+
| iso8859_14        | iso-8859-14, latin8, L8          | 凯尔特语                         |
+-------------------+----------------------------------+----------------------------------+
| iso8859_15        | iso-8859-15, latin9, L9          | 西欧                             |
+-------------------+----------------------------------+----------------------------------+
| iso8859_16        | iso-8859-16, latin10, L10        | 东南欧                           |
+-------------------+----------------------------------+----------------------------------+
| johab             | cp1361, ms1361                   | 韩语                             |
+-------------------+----------------------------------+----------------------------------+
| koi8_r            |                                  | 俄语                             |
+-------------------+----------------------------------+----------------------------------+
| koi8_t            |                                  | 塔吉克  Added in version 3.5.    |
+-------------------+----------------------------------+----------------------------------+
| koi8_u            |                                  | 乌克兰语                         |
+-------------------+----------------------------------+----------------------------------+
| kz1048            | kz_1048, strk1048_2002, rk1048   | 哈萨克语  Added in version 3.5.  |
+-------------------+----------------------------------+----------------------------------+
| mac_cyrillic      | maccyrillic                      | 白俄罗斯语，保加利亚语，马其顿语 |
|                   |                                  | ，俄语，塞尔维亚语               |
+-------------------+----------------------------------+----------------------------------+
| mac_greek         | macgreek                         | 希腊语                           |
+-------------------+----------------------------------+----------------------------------+
| mac_iceland       | maciceland                       | 冰岛语                           |
+-------------------+----------------------------------+----------------------------------+
| mac_latin2        | maclatin2, maccentraleurope,     | 中欧和东欧                       |
|                   | mac_centeuro                     |                                  |
+-------------------+----------------------------------+----------------------------------+
| mac_roman         | macroman, macintosh              | 西欧                             |
+-------------------+----------------------------------+----------------------------------+
| mac_turkish       | macturkish                       | 土耳其语                         |
+-------------------+----------------------------------+----------------------------------+
| ptcp154           | csptcp154, pt154, cp154,         | 哈萨克语                         |
|                   | cyrillic-asian                   |                                  |
+-------------------+----------------------------------+----------------------------------+
| shift_jis         | csshiftjis, shiftjis, sjis,      | 日语                             |
|                   | s_jis                            |                                  |
+-------------------+----------------------------------+----------------------------------+
| shift_jis_2004    | shiftjis2004, sjis_2004,         | 日语                             |
|                   | sjis2004                         |                                  |
+-------------------+----------------------------------+----------------------------------+
| shift_jisx0213    | shiftjisx0213, sjisx0213,        | 日语                             |
|                   | s_jisx0213                       |                                  |
+-------------------+----------------------------------+----------------------------------+
| utf_32            | U32, utf32                       | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_32_be         | UTF-32BE                         | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_32_le         | UTF-32LE                         | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_16            | U16, utf16                       | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_16_be         | UTF-16BE                         | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_16_le         | UTF-16LE                         | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_7             | U7, unicode-1-1-utf-7            | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_8             | U8, UTF, utf8, cp65001           | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+
| utf_8_sig         |                                  | 所有语言                         |
+-------------------+----------------------------------+----------------------------------+

在 3.4 版本发生变更: utf-16* 和 utf-32* 编码器将不再允许编码代理码位
("U+D800"--"U+DFFF")。 utf-32* 解码器将不再解码与代理码位相对应的字节
序列。

在 3.8 版本发生变更: "cp65001" 现在是 "utf_8" 的一个别名。

在 3.14 版本发生变更: 在 Windows 系统上，现在所有代码页都可以使用
"cpXXX" 编解码器了。


Python 专属的编码格式
=====================

有一些预定义编解码器是 Python 专属的，因此它们在 Python 之外没有意义。
这些编解码器按其所预期的输入和输出类型在下表中列出（请注意虽然文本编码
是编解码器最常见的使用场景，但下层的编解码器架构支持任意数据转换而不仅
是文本编码）。 对于非对称编解码器，该列描述的含义是编码方向。


文字编码
--------

以下编解码器提供了 "str" 到 "bytes" 的编码和 *bytes-like object* 到
"str" 的解码，类似于 Unicode 文本编码。

+----------------------+-----------+-----------------------------+
| 编码                 | 别名      | 含意                        |
|======================|===========|=============================|
| idna                 |           | 实现 **RFC 3490**，另请参阅 |
|                      |           | "encodings.idna" 。仅支持   |
|                      |           | "errors='strict'" 。        |
+----------------------+-----------+-----------------------------+
| mbcs                 | ansi,     | Windows 专属：根据 ANSI 代  |
|                      | dbcs      | 码页（CP_ACP）对操作数进行  |
|                      |           | 编码。                      |
+----------------------+-----------+-----------------------------+
| oem                  |           | Windows 专属：根据 OEM 代码 |
|                      |           | 页（CP_OEMCP）对操作数进行  |
|                      |           | 编码。  Added in version    |
|                      |           | 3.6.                        |
+----------------------+-----------+-----------------------------+
| palmos               |           | PalmOS 3.5 的编码格式       |
+----------------------+-----------+-----------------------------+
| punycode             |           | 实现 **RFC 3492**。 不支持  |
|                      |           | 有状态编解码器。            |
+----------------------+-----------+-----------------------------+
| raw_unicode_escape   |           | Latin-1 编码格式附带对其他  |
|                      |           | 码位以 "\u*XXXX*" 和        |
|                      |           | "\U*XXXXXXXX*" 进行编码 。  |
|                      |           | 现有的反斜杠不会以任何方式  |
|                      |           | 转义。 它被用于 Python 的   |
|                      |           | pickle 协议。               |
+----------------------+-----------+-----------------------------+
| undefined            |           | 该编解码器应当仅用于测试目  |
|                      |           | 的。  所有转换都将引发异常  |
|                      |           | ，甚至对空字符串也不例外。  |
|                      |           | 错误处理方案会被忽略。      |
+----------------------+-----------+-----------------------------+
| unicode_escape       |           | 适合用于以 ASCII 编码的     |
|                      |           | Python 源代码中的 Unicode   |
|                      |           | 字面值内容的编码格式 ，但引 |
|                      |           | 号不会被转义。 对 Latin-1   |
|                      |           | 源代码进行解码。 请注意     |
|                      |           | Python 源代码 实际上默认使  |
|                      |           | 用 UTF-8。                  |
+----------------------+-----------+-----------------------------+

在 3.8 版本发生变更: "unicode_internal" 编解码器已被移除。


二进制转换
----------

以下编解码器提供了二进制转换: *bytes-like object* 到 "bytes" 的映射。
它们不被 "bytes.decode()" 所支持（该方法只生成 "str" 类型的输出）。

+------------------------+--------------------+--------------------------------+--------------------------------+
| 编码                   | 别名               | 含意                           | 编码器/解码器                  |
|========================|====================|================================|================================|
| base64_codec [1]       | base64, base_64    | 将操作数转换为多行 MIME base64 | "base64.encodebytes()" /       |
|                        |                    | (结果总是包含一个末尾的        | "base64.decodebytes()"         |
|                        |                    | "'\n'")  在 3.4 版本发生变更:  |                                |
|                        |                    | 接受任意 *bytes-like object*   |                                |
|                        |                    | 作为输入用于编码和解 码        |                                |
+------------------------+--------------------+--------------------------------+--------------------------------+
| bz2_codec              | bz2                | 使用bz2压缩操作数              | "bz2.compress()" /             |
|                        |                    |                                | "bz2.decompress()"             |
+------------------------+--------------------+--------------------------------+--------------------------------+
| hex_codec              | hex                | 将操作数转换为十六进制表示，每 | "binascii.b2a_hex()" /         |
|                        |                    | 个字节有两位数                 | "binascii.a2b_hex()"           |
+------------------------+--------------------+--------------------------------+--------------------------------+
| quopri_codec           | quopri,            | 将操作数转换为 MIME 带引号的可 | "quopri.encode()" 且           |
|                        | quotedprintable,   | 打印数据                       | "quotetabs=True" /             |
|                        | quoted_printable   |                                | "quopri.decode()"              |
+------------------------+--------------------+--------------------------------+--------------------------------+
| uu_codec               | uu                 | 使用uuencode转换操作数         |                                |
+------------------------+--------------------+--------------------------------+--------------------------------+
| zlib_codec             | zip, zlib          | 使用gzip压缩操作数             | "zlib.compress()" /            |
|                        |                    |                                | "zlib.decompress()"            |
+------------------------+--------------------+--------------------------------+--------------------------------+

[1] 除了 *字节类对象*，"'base64_codec'" 也接受仅包含 ASCII 的 "str" 实
    例用于解码

Added in version 3.2: 恢复二进制转换。

在 3.4 版本发生变更: 恢复二进制转换的别名。


独立编解码器函数
----------------

下列函数提供了与编解码器类似的编码和解码功能，但并不能通过
"codecs.encode()" 或 "codecs.decode()" 作为已命名的编解码器使用。 它们
仅供内部使用（例如，由 "pickle" 使用）且其行为类似于已在 Python 3 中被
移除的 "string_escape" 编解码器。

codecs.escape_encode(input, errors=None)

   使用转义序列对 *input* 进行编码。 类似于字节串上的 "repr()" 产生转
   义后的字节值。

   *input* 必须是一个 "bytes" 对象。

   返回一个元组 "(output, length)" 其中 *output* 为 "bytes" 对象而
   *length* 为消耗的字节数。

codecs.escape_decode(input, errors=None)

   将 *input* 从转义序列解码回原始字节串。

   *input* 必须是一个 *bytes-like object*。

   返回一个元组 "(output, length)" 其中 *output* 为 "bytes" 对象而
   *length* 为消耗的字节数。


文字转换
--------

以下编解码器提供了文本转换: "str" 到 "str" 的映射。 它不被
"str.encode()" 所支持（该方法只生成 "bytes" 类型的输出）。

+----------------------+-----------+-----------------------------+
| 编码                 | 别名      | 含意                        |
|======================|===========|=============================|
| rot_13               | rot13     | 返回操作数的凯撒密码加密结  |
|                      |           | 果                          |
+----------------------+-----------+-----------------------------+

Added in version 3.2: 恢复 "rot_13" 文本转换。

在 3.4 版本发生变更: 恢复 "rot13" 别名。


"encodings" --- Encodings package
=================================

这个模块实现了以下函数：

encodings.normalize_encoding(encoding)

   规范化编码格式名称 *encoding*。

   规范化的运作方式如下：用于 Python 包名称的点号除外的所有非字母数字
   类字符都会被缩减替换为一个下划线，开头和末尾的下划线将被移除。 例如
   ，"' -;#'" 将变为 "'_'"。

   请注意 *encoding* 应当仅用 ASCII 字符。

备注:

  以下函数不应被直接使用，除非出于测试目的；应当改用 "codecs.lookup()"
  。

encodings.search_function(encoding)

   搜索与给定的编码格式名称 *encoding* 相对应的编解码器模块。

   此函数首先会使用 "normalize_encoding()" 来规范化 *encoding*，然后查
   找相应的别名。 它会尝试使用别名或规范化的名称从 encodings 包导入一
   个编解码器模块。 如果模块被找到并且它定义了有效的返回
   "codecs.CodecInfo" 对象的 "getregentry()" 函数，该编解码器将被缓存
   并被返回。

   如果该编解码器模块定义了 "getaliases()" 函数则任何被返回的别名都将
   被注册以供将来使用。

encodings.win32_code_page_search_function(encoding)

   搜索形式为 "cpXXXX" 的 Windows 代码页编码格式 *encoding*。

   如果代码页有效且受到支持，则返回与它对应的 "codecs.CodecInfo" 对象
   。

   适用范围: Windows.

   Added in version 3.14.

这个模块实现了以下异常：

exception encodings.CodecRegistryError

   当一个编解码器无效或不兼容时引发。


"encodings.idna" --- Internationalized Domain Names in Applications
===================================================================

此模块实现了 **RFC 3490** (应用程序中的国际化域名) 和 **RFC 3492**
(Nameprep: 用于国际化域名 (IDN) 的 Stringprep 配置文件)。 它是在
"punycode" 编码格式和 "stringprep" 的基础上构建的。

如果你需要来自 **RFC 5891** 和 **RFC 5895** 的 IDNA 2008 标准，请使用
第三方的 idna 模块。

这些 RFC 共同定义了一个在域名中支持非 ASCII 字符的协议。 一个包含非
ASCII 字符的域名 (例如 "www.Alliancefrançaise.nu") 会被转换为兼容
ASCII 的编码格式 (简称 ACE，例如 "www.xn--alliancefranaise-npb.nu")。
随后此域名的 ACE 形式可以用于所有由于特定协议而不允许使用任意字符的场
合，例如 DNS 查询，HTTP *Host* 字段等等。 此转换是在应用中进行的；如有
可能将对用户不可见：应用应当透明地将 Unicode 域名标签转换为线上的 IDNA
，并在 ACE 标签被呈现给用户之前将其转换回 Unicode。

Python 以多种方式支持这种转换:  "idna" 编解码器执行 Unicode 和 ACE 之
间的转换，基于在 **section 3.1 of RFC 3490** 中定义的分隔字符将输入字
符串拆分为标签，再根据需要将每个标签转换为 ACE，相反地又会基于 "." 分
隔符将输入字节串拆分为标签，再将找到的任何 ACE 标签转换为 Unicode。 此
外，"socket" 模块可透明地将 Unicode 主机名转换为 ACE，以便应用在将它们
传给 socket 模块时无须自行转换主机名。 除此之外，许多包含以主机名作为
函数参数的模块例如 "http.client" 和 "ftplib" 都接受 Unicode 主机名（并
且 "http.client" 也会在 *Host* 字段中透明地发送 IDNA 主机名，如果它需
要发送该字段的话）。

当从线路接收主机名时（例如反向名称查找），到 Unicode 的转换不会自动被
执行：希望向用户提供此种主机名的应用应当将它们解码为 Unicode。

The module "encodings.idna" also implements the nameprep procedure,
which performs certain normalizations on host names, to achieve case-
insensitivity of international domain names, and to unify similar
characters. The nameprep functions can be used directly if desired.

encodings.idna.nameprep(label)

   返回 *label* 经过名称处理操作的版本。 该实现目前基于查询字符串，因
   此 "AllowUnassigned" 为真值。

encodings.idna.ToASCII(label)

   将标签转换为 ASCII，规则定义见 **RFC 3490**。 "UseSTD3ASCIIRules"
   预设为假值。

encodings.idna.ToUnicode(label)

   将标签转换为 Unicode，规则定义见 **RFC 3490**。


"encodings.mbcs" --- Windows ANSI codepage
==========================================

此模块实现ANSI代码页（CP_ACP）。

适用范围: Windows.

在 3.2 版本发生变更: 在 3.2 版之前， *errors* 参数会被忽略；总是会使用
"'replace'" 进行编码，并使用 "'ignore'" 进行解码。

在 3.3 版本发生变更: 支持任何错误处理


"encodings.utf_8_sig" --- UTF-8 codec with BOM signature
========================================================

此模块实现了 UTF-8 编解码器的一个变种：在编码时将把 UTF-8 已编码 BOM
添加到 UTF-8 编码字节数据的开头。 对于有状态编码器此操作只执行一次（当
首次写入字节流时）。 在解码时将跳过数据开头作为可选项的 UTF-8 已编码
BOM。
