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 标准编码 编解码器一起使用
值 |
含义 |
---|---|
|
引发 |
|
忽略格式错误的数据并继续,不发出任何进一步的通知。在 |
|
用替换标记替换。编码时,使用 |
|
用反斜杠转义序列替换。编码时,使用 Unicode 代码点的十六进制形式,格式为 |
|
解码时,将字节替换为范围从 |
以下错误处理程序仅适用于编码(在 文本编码 中)
值 |
含义 |
---|---|
|
替换为 XML/HTML 数字字符引用,它是 Unicode 代码点的十进制形式,格式为 |
|
替换为 |
此外,以下错误处理程序特定于给定的编解码器
值 |
编解码器 |
含义 |
---|---|---|
|
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 参数。
对于编码,将使用
UnicodeEncodeError
实例调用 error_handler,该实例包含有关错误位置的信息。错误处理程序必须引发此异常或其他异常,或者返回一个元组,其中包含不可编码部分输入的替换内容以及编码应继续的位置。替换内容可以是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'
错误处理。格式错误的数据将被反斜杠转义序列替换。编码时,使用 Unicode 代码点的十六进制形式,格式为
\xhh
\uxxxx
\Uxxxxxxxx
。解码时,使用字节值的十六进制形式,格式为\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
是最常见的状态。(比整数更复杂的状态可以通过封送/序列化状态并将结果字符串的字节编码为整数来转换为整数。)
- 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
的状态,以便将先前缓冲的输入馈送到解码器会使其返回到先前的状态,而不会产生任何输出。(比整数更复杂的附加状态信息可以通过将信息编组/序列化并将结果字符串的字节编码为整数来转换为整数。)
- 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,则将其作为 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
)。由于任何字符映射编码的文件以这些字节值开头的可能性都相当小(例如,在 iso-8859-1 中,这些字节值将映射到
带分音符号的小写拉丁字母 I右双引号倒置问号
),这增加了从字节序列中正确猜测出 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 兼容
编解码器 |
别名 |
语言 |
---|---|---|
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 |
越南语 |
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 |
塔吉克语 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 文本编码。
编解码器 |
别名 |
含义 |
---|---|---|
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
输出)。
编解码器 |
别名 |
含义 |
编码器 / 解码器 |
---|---|---|---|
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
输出)。
编解码器 |
别名 |
含义 |
---|---|---|
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。