7.2. codecs — 编解码器注册表和基类 — Python 文档

来自菜鸟教程
Python/docs/3.6/library/codecs
跳转至:导航、​搜索

7.2. 编解码器 — 编解码器注册表和基类

源代码: :source:`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 Interface)。 函数或方法应在无状态模式下工作。

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 提供的输入进行迭代编码。 这个函数是一个生成器errors 参数(以及任何其他关键字参数)被传递到增量编码器。

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

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

使用增量解码器对 iterator 提供的输入进行迭代解码。 这个函数是一个生成器errors 参数(以及任何其他关键字参数)被传递到增量解码器。

此功能要求编解码器接受 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 取决于平台的原生字节顺序,BOM 是 [X156UTFX] 的别名] , BOM_LE 用于 BOM_UTF16_LEBOM_BE 用于 BOM_UTF16_BE。 其他代表 UTF-8 和 UTF-32 编码的 BOM。

7.2.1. 编解码器基类

codecs 模块定义了一组基类,这些基类定义了用于处理编解码器对象的接口,也可以用作自定义编解码器实现的基础。

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

7.2.1.1. 错误处理程序

为了简化和标准化错误处理,编解码器可以通过接受 errors 字符串参数来实现不同的错误处理方案。 以下字符串值由所有标准 Python 编解码器定义和实现:

价值 意义
'strict' 引发 UnicodeError(或子类); 这是默认设置。 在 strict_errors() 中实现。
'ignore' 忽略格式错误的数据并继续,恕不另行通知。 在 ignore_errors() 中实现。

以下错误处理程序仅适用于 文本编码

价值 意义
'replace' 用合适的替换标记替换; Python 将使用官方的 U+FFFD REPLACEMENT CHARACTER 作为内置编解码器进行解码,以及 '?' 关于编码。 在 replace_errors() 中实现。
'xmlcharrefreplace' 替换为适当的 XML 字符引用(仅用于编码)。 在 xmlcharrefreplace_errors() 中实现。
'backslashreplace' 替换为反斜杠转义序列。 在 backslashreplace_errors() 中实现。
'namereplace' 替换为 \N{...} 转义序列(仅用于编码)。 在 namereplace_errors() 中实现。
'surrogateescape' 在解码时,用范围从 U+DC80U+DCFF 的单个代理代码替换字节。 当在编码数据时使用 'surrogateescape' 错误处理程序时,此代码将被转换回相同的字节。 (有关更多信息,请参阅 PEP 383。)

此外,以下错误处理程序特定于给定的编解码器:

价值 编解码器 意义
'surrogatepass' utf-8、utf-16、utf-32、utf-16-be、utf-16-le、utf-32-be、utf-32-le 允许对代理代码进行编码和解码。 这些编解码器通常将代理的存在视为错误。

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_handlererror_handler 参数会在编码和解码过程中被调用,当 name 被指定为错误参数时,如果出现错误。

对于编码,将使用 UnicodeEncodeError 实例调用 error_handler,该实例包含有关错误位置的信息。 错误处理程序必须引发此异常或不同的异常,或者返回一个元组,替换输入的不可编码部分和编码应继续的位置。 替换可以是 strbytes。 如果替换是字节,编码器将简单地将它们复制到输出缓冲区中。 如果替换是字符串,编码器将对替换进行编码。 在指定位置的原始输入上继续编码。 负位置值将被视为相对于输入字符串的末尾。 如果结果位置超出范围,将引发 IndexError

解码和翻译的工作类似,除了 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])

解码对象 input 并返回一个元组(输出对象,消耗的长度)。 例如,对于 文本编码 ,解码将使用特定字符集编码的字节对象转换为字符串对象。

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

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

该方法可能不会在 Codec 实例中存储状态。 将 StreamReader 用于必须保持状态以提高解码效率的编解码器。

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


7.2.1.3. 增量编码和解码

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

encode()/decode() 方法的调用的合并输出与所有单个输入合并为一个相同,并且此输入使用无状态编码器/解码器。

7.2.1.3.1. 增量编码器对象

IncrementalEncoder 类用于在多个步骤中对输入进行编码。 它定义了每个增量编码器必须定义的以下方法,以便与 Python 编解码器注册表兼容。

class codecs.IncrementalEncoder(errors='strict')

IncrementalEncoder 实例的构造函数。

所有增量编码器都必须提供此构造函数接口。 它们可以自由添加额外的关键字参数,但 Python 编解码器注册表仅使用此处定义的参数。

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

errors 参数将分配给同名的属性。 分配给此属性可以在 IncrementalEncoder 对象的生命周期内在不同的错误处理策略之间切换。

encode(object[, final])

编码 object(考虑编码器的当前状态)并返回生成的编码对象。 如果这是最后一次调用 encode() final 必须为真(默认为假)。

reset()

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

getstate()

返回编码器的当前状态,它必须是一个整数。 实现应该确保 0 是最常见的状态。 (比整数更复杂的状态可以通过编组/酸洗状态并将结果字符串的字节编码为整数来转换为整数)。

setstate(state)

设置编码器状态为statestate 必须是 getstate() 返回的编码器状态。


7.2.1.3.2. 增量解码器对象

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)

设置编码器状态为statestate 必须是 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() 方法永远不会返回比请求更多的数据,但如果没有足够的可用数据,它可能会返回更少的数据。

size 参数指示要读取以进行解码的编码字节或代码点的近似最大数量。 解码器可以适当地修改此设置。 默认值 -1 表示尽可能多地读取和解码。 此参数旨在防止必须一步解码大文件。

firstline 标志表示如果后面的行有解码错误,只返回第一行就足够了。

该方法应该使用贪婪读取策略,这意味着它应该读取编码定义和给定大小允许的尽可能多的数据,例如 如果流上有可选的编码结尾或状态标记,则也应阅读这些内容。

readline([size[, keepends]])

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

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

如果 keepends 为假,则行尾将从返回的行中删除。

readlines([sizehint[, keepends]])

读取输入流上可用的所有行,并将它们作为行列表返回。

行结束符使用编解码器的解码器方法实现,如果 keepends 为真,则将其包含在列表条目中。

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

reset()

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

请注意,不应发生流重新定位。 这种方法主要是为了能够从解码错误中恢复。

除了上述方法之外,StreamReader 还必须从底层流继承所有其他方法和属性。


7.2.1.4.3. StreamReaderWriter 对象

StreamReaderWriter 是一个方便的类,它允许包装在读写模式下工作的流。

设计是这样的,人们可以使用 lookup() 函数返回的工厂函数来构造实例。

class codecs.StreamReaderWriter(stream, Reader, Writer, errors='strict')
创建一个 StreamReaderWriter 实例。 stream 必须是类文件对象。 ReaderWriter 必须是提供 StreamReaderStreamWriter 接口的工厂函数或类。 错误处理的完成方式与为流读取器和写入器定义的方式相同。

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


7.2.1.4.4. StreamRecoder 对象

StreamRecoder 将数据从一种编码转换为另一种编码,这在处理不同的编码环境时有时很有用。

设计是这样的,人们可以使用 lookup() 函数返回的工厂函数来构造实例。

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

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

您可以使用这些对象从例如 Latin-1 到 UTF-8 并返回。

stream 参数必须是一个类似文件的对象。

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

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

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


7.2.2. 编码和 Unicode

字符串在内部存储为 0x00x10FFFF 范围内的代码点序列。 (有关实现的更多详细信息,请参阅 PEP 393。)一旦在 CPU 和内存之外使用字符串对象,字节顺序以及如何将这些数组存储为字节就成为一个问题。 与其他编解码器一样,将字符串序列化为字节序列称为 encoding,从字节序列重新创建字符串称为 decoding。 有多种不同的文本序列化编解码器,它们被统称为文本编码

最简单的文本编码(称为 '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)

还有另一组编码(所谓的 charmap 编码)选择所有 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 110xxxxxx 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

如果没有外部信息,就不可能可靠地确定使用哪种编码对字符串进行编码。 每个charmap 编码可以解码任何随机字节序列。 然而,这对于 UTF-8 来说是不可能的,因为 UTF-8 字节序列的结构不允许任意字节序列。 为了提高检测 UTF-8 编码的可靠性,Microsoft 为其记事本程序发明了 UTF-8 的变体(Python 2.5 称为 "utf-8-sig"):在将任何 Unicode 字符写入到文件中写入了 UTF-8 编码的 BOM(看起来像这样的字节序列:0xef0xbb0xbf)。 因为任何 charmap 编码的文件都不太可能以这些字节值开头(例如 映射到

带分音符的拉丁文小写字母 I

右指向双角引号

倒置的问号

在 iso-8859-1 中),这增加了可以从字节序列中正确猜测 utf-8-sig 编码的可能性。 所以这里的 BOM 不是用来确定用于生成字节序列的字节顺序,而是用作帮助猜测编码的签名。 在编码 utf-8-sig 编解码器时,会将 0xef0xbb0xbf 作为前三个字节写入文件。 在解码时 utf-8-sig 将跳过这三个字节,如果它们出现在文件中的前三个字节。 在 UTF-8 中,不鼓励使用 BOM,通常应避免使用。


7.2.3. 标准编码

Python 附带了许多内置的编解码器,它们要么实现为 C 函数,要么使用字典作为映射表。 下表按名称列出了编解码器,以及一些常见的别名,以及可能使用该编码的语言。 别名列表和语言列表都不是详尽无遗的。 请注意,仅大小写不同或使用连字符而不是下划线的拼写替代方案也是有效的别名; 因此,例如 'utf-8''utf_8' 编解码器的有效别名。

许多字符集支持相同的语言。 它们在个别字符上有所不同(例如 是否支持 EURO SIGN),以及将字符分配给代码位置。 特别是对于欧洲语言,通常存在以下变体:

  • ISO 8859 代码集
  • Microsoft Windows 代码页,通常源自 8859 代码集,但将控制字符替换为其他图形字符
  • 一个 IBM EBCDIC 代码页
  • 一个 IBM PC 代码页,与 ASCII 兼容
编解码器 别名 语言
ASCII码 646, us-ascii 英语
大5 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 视窗-1250 中欧和东欧
cp1251 视窗-1251 保加利亚语、白俄罗斯语、马其顿语、俄语、塞尔维亚语
cp1252 视窗-1252 西欧
cp1253 视窗-1253 希腊语
cp1254 视窗-1254 土耳其语
cp1255 视窗-1255 希伯来语
cp1256 视窗-1256 阿拉伯语
cp1257 视窗-1257 波罗的海语言
cp1258 视窗-1258 越南语
cp65001

仅限 Windows:Windows UTF-8 (CP_UTF8)

3.3 版中的新功能。


euc_jp eucjp, ujis, ujis 日语
euc_jis_2004 jisx0213, eucjis2004 日语
euc_jisx0213 eujisx0213 日语
euc_kr euckr, 韩语, ksc5601, ks_c-5601, ks_c-5601-1987, ksx1001, ks_x-1001 韩语
gb2312 中文, csiso58gb231280, euc-cn, euccn, eucgb2312-cn, gb2312-1980, gb2312-80, iso-ir-58 简体中文
国标 936、cp936、ms936 统一中文
国标18030 GB18030-2000 统一中文
赫兹 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 韩语
拉丁语_1 iso-8859-1、iso8859-1、8859、cp819、拉丁语、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,西里尔字母 保加利亚语、白俄罗斯语、马其顿语、俄语、塞尔维亚语
iso8859_6 iso-8859-6,阿拉伯语 阿拉伯语
iso8859_7 iso-8859-7, 希腊语, greek8 希腊语
iso8859_8 iso-8859-8,希伯来语 希伯来语
iso8859_9 iso-8859-9, latin5, L5 土耳其语
iso8859_10 iso-8859-10、latin6、L6 北欧语言
iso8859_11 iso-8859-11,泰国 泰语
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 东南欧
约哈布 cp1361, ms1361 韩语
锦鲤8_r 俄语
锦鲤8_t

塔吉克语

3.5 版中的新功能。


锦鲤8_u 乌克兰语
kz1048 kz_1048, strk1048_2002, rk1048

哈萨克语

3.5 版中的新功能。


mac_西里尔文 马西里尔 保加利亚语、白俄罗斯语、马其顿语、俄语、塞尔维亚语
mac_greek 麦克格里克 希腊语
mac_iceland 马西兰 冰岛语
mac_latin2 maclatin2, maccentraleurope 中欧和东欧
mac_roman 宏人,麦金塔 西欧
mac_turkish 土生土长的 土耳其语
ptcp154 csptcp154, pt154, cp154, 西里尔文-亚洲 哈萨克语
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* 和 utf-32* 编码器不再允许对代理代码点 (U+D800U+DFFF) 进行编码。 utf-32* 解码器不再解码与代理代码点对应的字节序列。


7.2.4. Python 特定编码

许多预定义的编解码器特定于 Python,因此它们的编解码器名称在 Python 之外没有任何意义。 这些根据预期的输入和输出类型列在下表中(请注意,虽然文本编码是编解码器最常见的用例,但底层编解码器基础结构支持任意数据转换,而不仅仅是文本编码)。 对于非对称编解码器,所述目的描述了编码方向。

7.2.4.1. 文本编码

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

编解码器 别名 目的
伊德娜 实现 RFC 3490,另见 encodings.idna。 仅支持 errors='strict'
主播 ansi, dbcs 仅限 Windows:根据 ANSI 代码页 (CP_ACP) 对操作数进行编码
原始设备制造商

仅限 Windows:根据 OEM 代码页 (CP_OEMCP) 对操作数进行编码

3.6 版中的新功能。


帕尔莫斯 PalmOS 3.5 编码
小码 实现 RFC 3492。 不支持有状态编解码器。
raw_unicode_escape 其他代码点使用 \uXXXX\UXXXXXXXX 的 Latin-1 编码。 现有的反斜杠不会以任何方式转义。 它用于 Python pickle 协议。
未定义 为所有转换引发异常,甚至是空字符串。 错误处理程序被忽略。
unicode_escape 编码适合作为 ASCII 编码的 Python 源代码中的 Unicode 文字的内容,但不转义引号。 从 Latin-1 源代码解码。 请注意 Python 源代码实际上默认使用 UTF-8。
unicode_internal

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

自 3.3 版起已弃用:此表示已被 PEP 393 废弃。



7.2.4.2. 二进制变换

以下编解码器提供二进制转换:bytes-like objectbytes 映射。 bytes.decode()(仅产生 str 输出)不支持它们。

编解码器 别名 目的 编码器/解码器
base64_codec 1 base64, base_64

将操作数转换为多行 MIME base64(结果总是包含一个尾随 '\n'

3.4 版更改: 接受任何 字节类对象 作为编码和解码的输入


base64.encodebytes() / base64.decodebytes()
bz2_codec bz2 使用 bz2 压缩操作数 bz2.compress() / bz2.decompress()
十六进制编解码器 十六进制 将操作数转换为十六进制表示,每字节两位数 binascii.b2a_hex() / binascii.a2b_hex()
quopri_codec quopri、quotedprintable、quoted_printable 将操作数转换为 MIME 引用的可打印 quopri.encode()quotetabs=True / quopri.decode()
uu_codec uu 使用 uuencode 转换操作数 uu.encode() / uu.decode()
zlib_codec 压缩包,zlib 使用 gzip 压缩操作数 zlib.compress() / zlib.decompress()
1
除了 bytes-like objects'base64_codec' 也接受 str 的 ASCII-only 实例进行解码

3.2 版新功能: 恢复二进制转换。


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


7.2.4.3. 文本变换

以下编解码器提供了文本转换:strstr 的映射。 str.encode() 不支持它(它只产生 bytes 输出)。

编解码器 别名 目的
腐烂_13 腐烂13 返回操作数的凯撒密码加密

3.2 版新功能: 恢复 rot_13 文本转换。


3.4 版更改: 恢复 rot13 别名。


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

该模块实现 RFC 3490(应用程序中的国际化域名)和 RFC 3492(Nameprep:国际化域名的 Stringprep 配置文件( IDN))。 它建立在 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 以多种方式支持这种转换:idna 编解码器在 Unicode 和 ACE 之间执行转换,根据 RFC 3490 的 第 3.1 节中定义的分隔符将输入字符串分成标签 并根据需要将每个标签转换为 ACE,相反,根据 . 分隔符将输入字节字符串分成标签,并将找到的任何 ACE 标签转换为 unicode。 此外,socket 模块透明地将 Unicode 主机名转换为 ACE,因此应用程序在将主机名传递给套接字模块时无需担心转换主机名本身。 最重要的是,具有主机名作为函数参数的模块,例如 http.clientftplib,接受 Unicode 主机名(http.client 然后也如果它发送该字段,则透明地在 Host 字段中发送 IDNA 主机名)。

当从线路接收主机名时(例如在反向名称查找中),不会执行到 Unicode 的自动转换:希望向用户显示此类主机名的应用程序应将它们解码为 Unicode。

encodings.idna模块也实现了nameprep过程,对主机名进行一定的规范化,实现国际域名不区分大小写,统一相似字符。 如果需要,可以直接使用 nameprep 函数。

encodings.idna.nameprep(label)
返回 label 的名称准备版本。 该实现当前假定查询字符串,因此 AllowUnassigned 为真。
encodings.idna.ToASCII(label)
按照 RFC 3490 中的规定,将标签转换为 ASCII。 UseSTD3ASCIIRules 被假定为假。
encodings.idna.ToUnicode(label)
按照 RFC 3490 中的规定,将标签转换为 Unicode。


7.2.6. 编码.mbcs — Windows ANSI 代码页

根据 ANSI 代码页 (CP_ACP) 对操作数进行编码。

可用性:仅限 Windows。

3.3 版更改: 支持任何错误处理程序。


3.2 版本更改: 3.2 之前, errors 参数被忽略; 'replace' 一直用于编码,'ignore' 用于解码。


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

该模块实现了 UTF-8 编解码器的一个变体:在编码 UTF-8 编码的 BOM 时,将附加到 UTF-8 编码的字节。 对于有状态编码器,这仅执行一次(在第一次写入字节流时)。 对于解码,将跳过数据开头的可选 UTF-8 编码 BOM。