7.2. codecs — 编解码器注册和相关基类

源代码: Lib/codecs.py


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

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

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.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

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

streamwriter
streamreader

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

为了简化对各种编解码器组件的访问,本模块提供了以下附加函数,它们使用 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

備註

搜索函数的注册目前是不可逆的,这在某些情况下可能导致问题,例如单元测试或模块重载等。

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

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

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

備註

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

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

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

buffering 的含义与内置 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 所提供的输入。 此函数属于 generatorerrors 参数(以及任何其他关键字参数)会被传递给增量式编码器。

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

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

使用增量式解码器通过迭代来解码由 iterator 所提供的输入。 此函数属于 generatorerrors 参数(以及任何其他关键字参数)会被传递给增量式解码器。

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

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

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_UTF16BOM_UTF16_BEBOM_UTF16_LE,具体取决于平台的本机字节顺序,BOMBOM_UTF16 的别名, BOM_LEBOM_UTF16_LE 的别名,BOM_BEBOM_UTF16_BE 的别名。 其他序列则表示 UTF-8 和 UTF-32 编码格式中的 BOM。

7.2.1. 编解码器基类

codecs 模块定义了一系列基类用来定义配合编解码器对象进行工作的接口,并且也可用作定制编解码器实现的基础。

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

7.2.1.1. 错误处理方案

To simplify and standardize error handling, codecs may implement different error handling schemes by accepting the errors string argument. The following string values are defined and implemented by all standard Python codecs:

含义
'strict' Raise UnicodeError (or a subclass); this is the default. Implemented in strict_errors().
'ignore' Ignore the malformed data and continue without further notice. Implemented in ignore_errors().

以下错误处理方案仅适用于 文本编码:

含义
'replace' Replace with a suitable replacement marker; Python will use the official U+FFFD REPLACEMENT CHARACTER for the built-in codecs on decoding, and 『?』 on encoding. Implemented in replace_errors().
'xmlcharrefreplace' Replace with the appropriate XML character reference (only for encoding). Implemented in xmlcharrefreplace_errors().
'backslashreplace' 使用带反斜杠的转义序列进行替换。 在 backslashreplace_errors() 中实现。
'namereplace' Replace with \N{...} escape sequences (only for encoding). Implemented in namereplace_errors().
'surrogateescape' On decoding, replace byte with individual surrogate code ranging from U+DC80 to U+DCFF. This code will then be turned back into the same byte when the 'surrogateescape' error handler is used when encoding the data. (See PEP 383 for more.)

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

编解码器 含义
'surrogatepass' utf-8, utf-16, utf-32, utf-16-be, utf-16-le, utf-32-be, utf-32-le Allow encoding and decoding of surrogate codes. These codecs normally treat the presence of surrogates as an error.

3.1 版新加入: 'surrogateescape''surrogatepass' 错误处理方案。

3.4 版更變: 'surrogatepass' 错误处理方案现在适用于 utf-16* 和 utf-32* 编解码器。

3.5 版新加入: 'namereplace' 错误处理方案。

3.5 版更變: 'backslashreplace' 错误处理方案现在适用于解码和转换。

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

codecs.register_error(name, error_handler)

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

For encoding, error_handler will be called with a UnicodeEncodeError instance, which contains information about the location of the error. The error handler must either raise this or a different exception, or return a tuple with a replacement for the unencodable part of the input and a position where encoding should continue. The replacement may be either str or bytes. If the replacement is bytes, the encoder will simply copy them into the output buffer. If the replacement is a string, the encoder will encode the replacement. Encoding continues on original input at the specified position. Negative position values will be treated as being relative to the end of the input string. If the resulting position is out of bound an IndexError will be raised.

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

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

codecs.lookup_error(name)

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

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

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

codecs.strict_errors(exception)

实现 'strict' 错误处理方案:每个编码或解码错误都会引发 UnicodeError

codecs.replace_errors(exception)

实现 'replace' 错误处理方案 (仅用于 文本编码):编码错误替换为 '?' (并由编解码器编码),解码错误替换为 '\ufffd' (Unicode 替换字符)。

codecs.ignore_errors(exception)

实现 'ignore' 错误处理方案:忽略错误格式的数据并且不加进一步通知就继续执行。

codecs.xmlcharrefreplace_errors(exception)

实现 'xmlcharrefreplace' 错误处理方案 (仅用于 文本编码 的编码过程):不可编码的字符将以适当的 XML 字符引用进行替换。

codecs.backslashreplace_errors(exception)

实现 'backslashreplace' 错误处理方案 (仅用于 文本编码):错误格式的数据将以带反斜杠的转义序列进行替换。

codecs.namereplace_errors(exception)

实现 'namereplace' 错误处理方案 (仅用于 文本编码 的编码过程):不可编码的字符将以 \N{...} 转义序列进行替换。

3.5 版新加入.

7.2.1.2. 无状态的编码和解码

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

Codec.encode(input[, errors])

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

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

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

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

Codec.decode(input[, errors])

Decodes the object input and returns a tuple (output object, length consumed). For instance, for a text encoding, decoding converts a bytes object encoded using a particular character set encoding to a string object.

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

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

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

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

7.2.1.3. 增量式的编码和解码

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

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

7.2.1.3.1. IncrementalEncoder 对象

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

class codecs.IncrementalEncoder(errors='strict')

IncrementalEncoder 实例的构造器。

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

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

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

encode(object[, final])

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

reset()

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

IncrementalEncoder.getstate()

Return the current state of the encoder which must be an integer. The implementation should make sure that 0 is the most common state. (States that are more complicated than integers can be converted into an integer by marshaling/pickling the state and encoding the bytes of the resulting string into an integer).

IncrementalEncoder.setstate(state)

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

7.2.1.3.2. IncrementalDecoder 对象

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

class codecs.IncrementalDecoder(errors='strict')

IncrementalDecoder 实例的构造器。

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

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

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

decode(object[, final])

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

reset()

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

getstate()

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

setstate(state)

Set the state of the encoder to state. state must be a decoder state returned by getstate().

7.2.1.4. 流式的编码和解码

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

7.2.1.4.1. StreamWriter 对象

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

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

StreamWriter 实例的构造器。

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

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

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

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

write(object)

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

writelines(list)

将拼接后的字符串列表写入到流(可能通过重用 write() 方法)。 标准的字节到字节编解码器不支持此方法。

reset()

刷新并重置用于保持状态的编解码器缓冲区。

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

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

7.2.1.4.2. StreamReader 对象

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

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

StreamReader 实例的构造器。

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

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

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

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

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

read([size[, chars[, firstline]]])

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

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

The size argument indicates the approximate maximum number of encoded bytes or code points to read for decoding. The decoder can modify this setting as appropriate. The default value -1 indicates to read and decode as much as possible. This parameter is intended to prevent having to decode huge files in one step.

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

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

readline([size[, keepends]])

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

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

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

readlines([sizehint[, keepends]])

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

Line-endings are implemented using the codec’s decoder method and are included in the list entries if keepends is true.

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

reset()

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

Note that no stream repositioning should take place. This method is primarily intended to be able to recover from decoding errors.

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

7.2.1.4.3. StreamReaderWriter 对象

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

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

class codecs.StreamReaderWriter(stream, Reader, Writer, errors)

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

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

7.2.1.4.4. StreamRecoder 对象

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

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

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

创建一个实现了双向转换的 StreamRecoder 实例: encodedecode 工作于前端 — 对代码可见的数据调用 read()write(),而 ReaderWriter 工作于后端 — stream 中的数据。

You can use these objects to do transparent transcodings from e.g. Latin-1 to UTF-8 and back.

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

encodedecode 参数必须遵循 Codec 接口。 ReaderWriter 必须为分别提供了 StreamReaderStreamWriter 接口对象的工厂函数或类。

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

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

7.2.2. 编码格式与 Unicode

Strings are stored internally as sequences of code points in range 0x00x10FFFF. (See PEP 393 for more details about the implementation.) Once a string object is used outside of CPU and memory, endianness and how these arrays are stored as bytes become an issue. As with other codecs, serialising a string into a sequence of bytes is known as encoding, and recreating the string from the sequence of bytes is known as decoding. There are a variety of different text serialisation codecs, which are collectivity referred to as text encodings.

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

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

所有这些编码格式只能对 Unicode 所定义的 1114112 个码位中的 256 个进行编码。 一种能够存储每个 Unicode 码位的简单而直接的办法就是将每个码位存储为四个连续的字节。 存在两种不同的可能性:以大端序存储或以小端序存储。 这两种编码格式分别被称为 UTF-32-BEUTF-32-LE。 它们的缺点可以举例说明:如果你在一台小端序的机器上使用 UTF-32-BE 则你将必须在编码和解码时翻转字节。 UTF-32 避免了这个问题:字节的排列将总是使用自然顺序。 当这些字节被具有不同字节顺序的 CPU 读取时,则必须进行字节翻转。 为了能够检测 UTF-16UTF-32 字节序列的大小端序,可以使用所谓的 BOM (「字节顺序标记」)。 这对应于 Unicode 字符 U+FEFF。 此字符可添加到每个 UTF-16UTF-32 字节序列的开头。 此字符的字节翻转版本 (0xFFFE) 是一个不可出现于 Unicode 文本中的非法字符。 因此当发现一个 UTF-16UTF-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-00000000U-0000007F 0xxxxxxx
U-00000080U-000007FF 110xxxxx 10xxxxxx
U-00000800U-0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
U-00010000U-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 2.5 称之为 "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

in iso-8859-1), this increases the probability that a utf-8-sig encoding can be correctly guessed from the byte sequence. So here the BOM is not used to be able to determine the byte order used for generating the byte sequence, but as a signature that helps in guessing the encoding. On encoding the utf-8-sig codec will write 0xef, 0xbb, 0xbf as the first three bytes to the file. On decoding utf-8-sig will skip those three bytes if they appear as the first three bytes in the file. In UTF-8, the use of the BOM is discouraged and should generally be avoided.

7.2.3. 标准编码

Python 自带了许多内置的编解码器,它们的实现或者是通过 C 函数,或者是通过映射表。 以下表格是按名称排序的编解码器列表,并提供了一些常见别名以及编码格式通常针对的语言。 别名和语言列表都不是详尽无遗的。 请注意仅有大小写区别或使用连字符替代下划线的拼写形式也都是有效的别名;因此,'utf-8''utf_8' 编解码器的有效别名。

CPython implementation detail: Some common encodings can bypass the codecs lookup machinery to improve performance. These optimization opportunities are only recognized by CPython for a limited set of aliases: utf-8, utf8, latin-1, latin1, iso-8859-1, mbcs (Windows only), ascii, utf-16, and utf-32. Using alternative spellings for these encodings may result in slower execution.

许多字符集都支持相同的语言。 它们在个别字符(例如是否支持 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

德语

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 日语
cp949 949, ms949, uhc 韩语
cp950 950, ms950 繁体中文
cp1006   乌尔都语
cp1026 ibm1026 土耳其语
cp1125 1125, ibm1125, cp866u, ruscii

乌克兰语

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 越南语
cp65001  

仅Windows: Windows UTF-8 (CP_UTF8)

3.3 版新加入.

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 West Europe
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  

塔吉克

3.5 版新加入.

koi8_u   乌克兰语
kz1048 kz_1048, strk1048_2002, rk1048

哈萨克语

3.5 版新加入.

mac_cyrillic maccyrillic 保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语
mac_greek macgreek 希腊语
mac_iceland maciceland 冰岛语
mac_latin2 maclatin2, maccentraleurope 中欧和东欧
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 所有语言
utf_8_sig   所有语言

3.4 版更變: utf-16* and utf-32* 编码器将不再允许编码代理码位 (U+D800U+DFFF)。 utf-32* 解码器将不再解码与代理码位相对应的字节序列。

7.2.4. Python 专属的编码格式

A number of predefined codecs are specific to Python, so their codec names have no meaning outside Python. These are listed in the tables below based on the expected input and output types (note that while text encodings are the most common use case for codecs, the underlying codec infrastructure supports arbitrary data transforms rather than just text encodings). For asymmetric codecs, the stated purpose describes the encoding direction.

7.2.4.1. 文字编码

以下编解码器提供了 strbytes 的编码和 bytes-like objectstr 的解码,类似于 Unicode 文本编码。

编码 别名 Purpose
idna   Implements RFC 3490, see also encodings.idna. Only errors='strict' is supported.
mbcs dbcs Windows only: Encode operand according to the ANSI codepage (CP_ACP)
palmos   Encoding of PalmOS 3.5
punycode   Implements RFC 3492. Stateful codecs are not supported.
raw_unicode_escape   Latin-1 编码格式附带对其他码位以 \uXXXX\UXXXXXXXX 进行编码。 现有反斜杠不会以任何方式转义。 它被用于 Python 的 pickle 协议。
undefined   所有转换都将引发异常,甚至对空字符串也不例外。 错误处理方案会被忽略。
unicode_escape   Encoding suitable as the contents of a Unicode literal in ASCII-encoded Python source code, except that quotes are not escaped. Decodes from Latin-1 source code. Beware that Python source code actually uses UTF-8 by default.
unicode_internal  

返回操作数的内部表示。 不支持有状态的编解码器。

3.3 版後已棄用: 此表示已被 PEP 393 所废弃。

7.2.4.2. 二进制转换

The following codecs provide binary transforms: bytes-like object to bytes mappings. They are not supported by bytes.decode() (which only produces str output).

编码 别名 Purpose 编码器/解码器
base64_codec [1] base64, base_64

Convert operand to multiline MIME base64 (the result always includes a trailing '\n')

3.4 版更變: 接受任意 bytes-like object 作为输入用于编码和解码

base64.encodebytes() / base64.decodebytes()
bz2_codec bz2 Compress the operand using bz2 bz2.compress() / bz2.decompress()
hex_codec hex Convert operand to hexadecimal representation, with two digits per byte binascii.b2a_hex() / binascii.a2b_hex()
quopri_codec quopri, quotedprintable, quoted_printable Convert operand to MIME quoted printable quopri.encode()quotetabs=True / quopri.decode()
uu_codec uu Convert the operand using uuencode uu.encode() / uu.decode()
zlib_codec zip, zlib Compress the operand using gzip zlib.compress() / zlib.decompress()
[1]除了 字节类对象'base64_codec' 也接受仅包含 ASCII 的 str 实例用于解码

3.2 版新加入: 恢复二进制转换。

3.4 版更變: 恢复二进制转换的别名。

7.2.4.3. 文字转换

The following codec provides a text transform: a str to str mapping. It is not supported by str.encode() (which only produces bytes output).

编码 别名 Purpose
rot_13 rot13 Returns the Caesar-cypher encryption of the operand

3.2 版新加入: 恢复 rot_13 文本转换。

3.4 版更變: 恢复 rot13 别名。

7.2.5. encodings.idna — 应用程序中的国际化域名

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

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

Python supports this conversion in several ways: the idna codec performs conversion between Unicode and ACE, separating an input string into labels based on the separator characters defined in section 3.1 (1) of RFC 3490 and converting each label to ACE as required, and conversely separating an input byte string into labels based on the . separator and converting any ACE labels found into unicode. Furthermore, the socket module transparently converts Unicode host names to ACE, so that applications need not be concerned about converting host names themselves when they pass them to the socket module. On top of that, modules that have host names as function parameters, such as http.client and ftplib, accept Unicode host names (http.client then also transparently sends an IDNA hostname in the Host field if it sends that field at all).

When receiving host names from the wire (such as in reverse name lookup), no automatic conversion to Unicode is performed: Applications wishing to present such host names to the user should decode them to Unicode.

encodings.idna 模块还实现了 nameprep 过程,该过程会对主机名执行特定的规范化操作,以实现国际域名的大小写不敏感特性与合并相似的字符。 如果有需要可以直接使用 nameprep 函数。

encodings.idna.nameprep(label)

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

encodings.idna.ToASCII(label)

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

encodings.idna.ToUnicode(label)

将标签转换为 Unicode,规则定义见 RFC 3490

7.2.6. encodings.mbcs — Windows ANSI代码页

Encode operand according to the ANSI codepage (CP_ACP).

Availability: Windows only.

3.3 版更變: 支持任何错误处理

3.2 版更變: 在 3.2 版之前, errors 参数会被忽略;总是会使用 'replace' 进行编码,并使用 'ignore' 进行解码。

7.2.7. encodings.utf_8_sig — 带BOM签名的UTF-8编解码器

This module implements a variant of the UTF-8 codec: On encoding a UTF-8 encoded BOM will be prepended to the UTF-8 encoded bytes. For the stateful encoder this is only done once (on the first write to the byte stream). For decoding an optional UTF-8 encoded BOM at the start of the data will be skipped.