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.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()
方法相同的接口(请参阅编解码器接口)。这些函数或方法应以无状态模式工作。
- 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)¶
取消注册编解码器搜索函数并清除注册表的缓存。 如果搜索函数未注册,则不执行任何操作。
在 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'
模式已被删除。
- 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_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。
编解码器基类¶
codecs
模块定义了一组基类,这些基类定义了使用编解码器对象的接口,也可以用作自定义编解码器实现的基础。
每个编解码器都必须定义四个接口,才能在 Python 中用作编解码器:无状态编码器、无状态解码器、流读取器和流写入器。流读取器和写入器通常重用无状态编码器/解码器来实现文件协议。编解码器作者还需要定义编解码器如何处理编码和解码错误。
错误处理程序¶
为了简化和标准化错误处理,编解码器可以通过接受 errors 字符串参数来实现不同的错误处理方案
>>> 'German ß, ♬'.encode(encoding='ascii', errors='backslashreplace')
b'German \\xdf, \\u266c'
>>> 'German ß, ♬'.encode(encoding='ascii', errors='xmlcharrefreplace')
b'German ß, ♬'
以下错误处理程序可用于所有 Python 标准编码编解码器
值 |
含义 |
---|---|
|
引发 |
|
忽略格式错误的数据,并继续而不另行通知。在 |
|
替换为替换标记。在编码时,使用 |
|
替换为反斜杠转义序列。在编码时,使用格式为 |
|
在解码时,用介于 |
以下错误处理程序仅适用于编码(在文本编码中)
值 |
含义 |
---|---|
|
替换为 XML/HTML 数字字符引用,它是格式为 |
|
替换为 |
此外,以下错误处理程序特定于给定的编解码器
值 |
编解码器 |
含义 |
---|---|---|
|
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_handler*。 当 *name* 被指定为 errors 参数时,在编码和解码过程中发生错误时将调用 *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,官方的替换字符)。
- codecs.backslashreplace_errors(exception)¶
实现
'backslashreplace'
错误处理。格式错误的数据将替换为反斜杠转义序列。 在编码时,使用格式为
\xhh
\uxxxx
\Uxxxxxxxx
的 Unicode 代码点的十六进制形式。 在解码时,使用格式为\xhh
的字节值的十六进制形式。3.5 版本更改: 可以用于解码和转换。
无状态编码和解码¶
基本 Codec
类定义了这些方法,这些方法也定义了无状态编码器和解码器的函数接口
- class codecs.Codec¶
- encode(input, errors='strict')¶
编码对象 *input* 并返回一个元组(输出对象,消耗的长度)。 例如,文本编码 使用特定的字符集编码(例如,
cp1252
或iso-8859-1
)将字符串对象转换为字节对象。*errors* 参数定义要应用的错误处理。 它默认为
'strict'
处理。该方法可能不会在
Codec
实例中存储状态。 对于必须保持状态才能使编码高效的编解码器,请使用StreamWriter
。编码器必须能够处理零长度输入,并在这种情况下返回输出对象类型的空对象。
- decode(input, errors='strict')¶
解码对象 *input* 并返回一个元组(输出对象,消耗的长度)。 例如,对于 文本编码,解码会将使用特定字符集编码编码的字节对象转换为字符串对象。
对于文本编码和字节到字节的编解码器,*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* 必须为 true(默认值为 false)。
- reset()¶
将编码器重置为初始状态。输出将被丢弃:如果需要,调用
.encode(object, final=True)
,传递一个空字节或文本字符串来重置编码器并获取输出。
- getstate()¶
返回编码器的当前状态,该状态必须为整数。实现应确保
0
是最常见的状态。(比整数更复杂的状态可以通过编组/pickle 该状态,并将结果字符串的字节编码为一个整数来转换为整数。)
- 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* 必须为 true(默认值为 false)。如果 *final* 为 true,则解码器必须完全解码输入并刷新所有缓冲区。如果无法做到这一点(例如,因为输入结尾处存在不完整的字节序列),则必须像无状态情况一样启动错误处理(这可能会引发异常)。
- reset()¶
将解码器重置为初始状态。
- getstate()¶
返回解码器的当前状态。这必须是一个包含两个项的元组,第一项必须是包含尚未解码的输入的缓冲区。第二项必须是一个整数,并且可以是附加状态信息。(实现应确保
0
是最常见的附加状态信息。)如果此附加状态信息为0
,则必须可以将解码器设置为没有缓冲输入且附加状态信息为0
的状态,以便将先前缓冲的输入馈送到解码器可以使其返回到之前的状态,而不会产生任何输出。(比整数更复杂的附加状态信息可以通过编组/pickle 该信息,并将结果字符串的字节编码为一个整数来转换为整数。)
- 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)¶
将对象的内容编码后写入流。
- reset()¶
重置用于保持内部状态的编解码器缓冲区。
调用此方法应确保输出上的数据处于干净状态,允许附加新的新鲜数据,而无需重新扫描整个流来恢复状态。
除了上述方法外,StreamWriter
还必须继承底层流的所有其他方法和属性。
StreamReader 对象¶
StreamReader
类是 Codec
的子类,并定义了每个流读取器为了与 Python 编解码器注册表兼容而必须定义的以下方法。
- class codecs.StreamReader(stream, errors='strict')¶
StreamReader
实例的构造函数。所有流读取器都必须提供此构造函数接口。它们可以自由添加额外的关键字参数,但只有此处定义的参数才会被 Python 编解码器注册表使用。
stream 参数必须是一个类似于文件的对象,打开用于读取文本或二进制数据,具体取决于特定的编解码器。
StreamReader
可以通过提供 errors 关键字参数来实现不同的错误处理方案。有关底层流编解码器可能支持的标准错误处理程序,请参见 错误处理程序。errors 参数将被赋值给同名的属性。赋值给此属性可以在
StreamReader
对象的生命周期内切换不同的错误处理策略。可以使用
register_error()
扩展 errors 参数允许的值的集合。- read(size=-1, chars=-1, firstline=False)¶
解码流中的数据并返回结果对象。
chars 参数指示要返回的已解码代码点或字节数。
read()
方法永远不会返回超过请求的数据,但如果可用数据不足,它可能会返回较少的数据。size 参数指示要读取进行解码的编码字节或代码点的近似最大数量。解码器可以根据需要修改此设置。默认值 -1 表示读取和解码尽可能多的数据。此参数旨在防止必须一步解码大型文件。
firstline 标志表示如果后面的行出现解码错误,则仅返回第一行就足够了。
该方法应使用贪婪读取策略,这意味着它应读取在编码定义和给定大小内允许的最大数据量,例如,如果流上提供了可选的编码结尾或状态标记,则也应读取这些数据。
- readline(size=None, keepends=True)¶
从输入流读取一行并返回解码后的数据。
如果给定 size,则将其作为大小参数传递给流的
read()
方法。如果 keepends 为 false,则将从返回的行中删除行尾。
- readlines(sizehint=None, keepends=True)¶
读取输入流上所有可用的行,并将它们作为行列表返回。
行尾是使用编解码器的
decode()
方法实现的,如果 keepends 为 true,则包含在列表条目中。如果给定 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
,则始终需要在编码和解码时交换字节。UTF-32
避免了这个问题:字节始终处于自然字节序。当具有不同字节序的 CPU 读取这些字节时,必须交换字节。为了能够检测 UTF-16
或 UTF-32
字节序列的字节序,有所谓的 BOM(“字节顺序标记”)。这是 Unicode 字符 U+FEFF
。此字符可以添加到每个 UTF-16
或 UTF-32
字节序列。此字符的字节交换版本 (0xFFFE
) 是一个非法字符,不得出现在 Unicode 文本中。因此,当 UTF-16
或 UTF-32
字节序列中的第一个字符看起来像是 U+FFFE
时,必须在解码时交换字节。不幸的是,字符 U+FEFF
还有第二个用途,作为 零宽度不换行空格
:一个没有宽度且不允许拆分单词的字符。例如,它可用于为连字算法提供提示。在 Unicode 4.0 中,使用 U+FEFF
作为 零宽度不换行空格
已被弃用(U+2060
(单词连接符
)承担此角色)。尽管如此,Unicode 软件仍然必须能够处理 U+FEFF
的两种角色:作为 BOM,它是确定编码字节的存储布局的设备,并在字节序列解码为字符串后消失;作为 零宽度不换行空格
,它是一个普通字符,将像任何其他字符一样解码。
还有另一种编码能够对全范围的 Unicode 字符进行编码:UTF-8。UTF-8 是一种 8 位编码,这意味着 UTF-8 中不存在字节顺序问题。UTF-8 字节序列中的每个字节都由两部分组成:标记位(最高有效位)和有效负载位。标记位是零到四个 1
位后跟一个 0
位的序列。Unicode 字符的编码方式如下(其中 x 是有效负载位,当连接时给出 Unicode 字符)
范围 |
编码 |
---|---|
|
0xxxxxxx |
|
110xxxxx 10xxxxxx |
|
1110xxxx 10xxxxxx 10xxxxxx |
|
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
Unicode 字符的最低有效位是最右边的 x 位。
由于 UTF-8 是 8 位编码,因此不需要 BOM,并且解码字符串中的任何 U+FEFF
字符(即使它是第一个字符)都被视为 零宽度不换行空格
。
在没有外部信息的情况下,不可能可靠地确定用于编码字符串的编码。每个字符映射编码都可以解码任何随机字节序列。但是,UTF-8 并非如此,因为 UTF-8 字节序列具有不允许任意字节序列的结构。为了提高 UTF-8 编码的检测可靠性,Microsoft 为其记事本程序发明了 UTF-8 的一种变体(Python 称之为 "utf-8-sig"
):在任何 Unicode 字符写入文件之前,写入 UTF-8 编码的 BOM(作为字节序列如下所示:0xef
、0xbb
、0xbf
)。由于任何字符映射编码文件都不太可能以这些字节值开头(例如,这将映射到
带分音符的拉丁小写字母 I右指双角引号倒问号
在 iso-8859-1 中),这增加了从字节序列中正确猜测 utf-8-sig
编码的可能性。因此,这里的 BOM 不是用来确定生成字节序列所使用的字节顺序,而是作为一种有助于猜测编码的签名。在编码时,utf-8-sig 编解码器会将 0xef
、0xbb
、0xbf
作为前三个字节写入文件。在解码时,如果 utf-8-sig
发现这三个字节出现在文件的开头,它会跳过这三个字节。在 UTF-8 中,不鼓励使用 BOM,通常应避免使用。
标准编码¶
Python 内置了许多编解码器,它们要么以 C 函数实现,要么使用字典作为映射表。下表按名称列出了编解码器,以及一些常见的别名和编码可能使用的语言。别名列表和语言列表均未详尽列出。请注意,仅大小写或使用连字符而不是下划线而不同的拼写变体也是有效的别名;因此,例如 'utf-8'
是 'utf_8'
编解码器的有效别名。
CPython 实现细节: 一些常见的编码可以绕过编解码器查找机制以提高性能。这些优化机会仅由 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 识别优化机会。
许多字符集支持相同的语言。它们在单个字符(例如,是否支持欧元符号)以及字符到代码位置的分配方面有所不同。特别是对于欧洲语言,通常存在以下变体:
ISO 8859 代码集
Microsoft Windows 代码页,它通常是从 8859 代码集派生的,但将控制字符替换为额外的图形字符
IBM EBCDIC 代码页
IBM PC 代码页,它与 ASCII 兼容
Codec |
别名 |
语言 |
---|---|---|
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, windows-31j |
日语 |
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 |
越南语 |
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, 西里尔语 |
保加利亚语、白俄罗斯语、马其顿语、俄语、塞尔维亚语 |
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 |
东南欧 |
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_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
的别名。
Python 特定编码¶
许多预定义的编解码器是 Python 特有的,因此它们的编解码器名称在 Python 之外没有意义。它们在下表中根据预期的输入和输出类型列出(请注意,虽然文本编码是编解码器最常见的用例,但底层编解码器基础结构支持任意数据转换,而不仅仅是文本编码)。对于不对称编解码器,所述含义描述了编码方向。
文本编码¶
以下编解码器提供 str
到 bytes
编码和 类似字节对象 到 str
解码,类似于 Unicode 文本编码。
Codec |
别名 |
含义 |
---|---|---|
idna |
实现 RFC 3490,另请参阅 |
|
mbcs |
ansi, dbcs |
仅限 Windows:根据 ANSI 代码页 (CP_ACP) 对操作数进行编码。 |
oem |
仅限 Windows:根据 OEM 代码页 (CP_OEMCP) 对操作数进行编码。 在 3.6 版本中添加。 |
|
palmos |
PalmOS 3.5 的编码。 |
|
punycode |
实现 RFC 3492。不支持有状态编解码器。 |
|
raw_unicode_escape |
Latin-1 编码,其他代码点使用 |
|
undefined |
为所有转换引发异常,即使是空字符串。错误处理程序将被忽略。 |
|
unicode_escape |
适合作为 ASCII 编码的 Python 源代码中 Unicode 字面量内容的编码,只是引号不会被转义。从 Latin-1 源代码解码。请注意,Python 源代码实际上默认使用 UTF-8。 |
在 3.8 版本中更改:删除了“unicode_internal”编解码器。
二进制转换¶
以下编解码器提供二进制转换:类字节对象 到 bytes
的映射。它们不受 bytes.decode()
的支持(它只产生 str
输出)。
Codec |
别名 |
含义 |
编码器/解码器 |
---|---|---|---|
base64_codec [1] |
base64, base_64 |
将操作数转换为多行 MIME base64 格式(结果始终包含尾部的 在 3.4 版本中更改: 接受任何 类字节对象 作为编码和解码的输入。 |
|
bz2_codec |
bz2 |
使用 bz2 压缩操作数。 |
|
hex_codec |
hex |
将操作数转换为十六进制表示,每个字节使用两位数字。 |
|
quopri_codec |
quopri, quotedprintable, quoted_printable |
将操作数转换为 MIME quoted printable 格式。 |
|
uu_codec |
uu |
使用 uuencode 转换操作数。 |
|
zlib_codec |
zip, zlib |
使用 gzip 压缩操作数。 |
在 3.2 版本中加入: 恢复了二进制转换。
在 3.4 版本中更改: 恢复了二进制转换的别名。
文本转换¶
以下编解码器提供文本转换:str
到 str
的映射。它不受 str.encode()
的支持(它只产生 bytes
输出)。
Codec |
别名 |
含义 |
---|---|---|
rot_13 |
rot13 |
返回操作数的凯撒密码加密结果。 |
在 3.2 版本中加入: 恢复了 rot_13
文本转换。
在 3.4 版本中更改: 恢复了 rot13
别名。
encodings.idna
— 应用程序中的国际化域名¶
该模块实现了 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 之间的转换,根据 RFC 3490 的 3.1 节 中定义的分隔符字符将输入字符串分成标签,并根据需要将每个标签转换为 ACE,反之,则根据 .
分隔符将输入字节字符串分成标签,并将找到的任何 ACE 标签转换为 Unicode。此外,socket
模块透明地将 Unicode 主机名转换为 ACE,因此当应用程序将主机名传递给 socket 模块时,无需担心自己转换主机名。最重要的是,将主机名作为函数参数的模块(例如 http.client
和 ftplib
)接受 Unicode 主机名(如果 http.client
发送 Host 字段,也会透明地在其中发送 IDNA 主机名)。
当从网络接收主机名(例如在反向名称查找中)时,不会自动执行到 Unicode 的转换:希望向用户显示此类主机名的应用程序应将其解码为 Unicode。
模块 encodings.idna
还实现了 nameprep 过程,该过程对主机名执行某些规范化,以实现国际域名的不区分大小写,并统一相似的字符。如果需要,可以直接使用 nameprep 函数。
- encodings.idna.nameprep(label)¶
返回 label 的 nameprep 版本。该实现当前假设为查询字符串,因此
AllowUnassigned
为 true。
encodings.mbcs
— Windows ANSI 代码页¶
此模块实现 ANSI 代码页 (CP_ACP)。
可用性:Windows。
在 3.2 版本中更改: 在 3.2 之前,errors 参数被忽略;'replace'
始终用于编码,'ignore'
用于解码。
在 3.3 版本中更改: 支持任何错误处理程序。
encodings.utf_8_sig
— 带有 BOM 签名的 UTF-8 编解码器¶
此模块实现 UTF-8 编解码器的一个变体。在编码时,UTF-8 编码的 BOM 将被添加到 UTF-8 编码的字节之前。对于有状态编码器,这只执行一次(在第一次写入字节流时)。在解码时,数据开头的可选 UTF-8 编码 BOM 将被跳过。