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()
方法相同接口的函数或方法(请参阅编解码器接口)。函数或方法应以无状态模式工作。
- 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'
模式已移除。自 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
对象。此函数是一个生成器。errors 参数(以及任何其他关键字参数)会传递给增量编码器。此函数要求编解码器接受文本
str
对象进行编码。因此,它不支持字节到字节的编码器,例如base64_codec
。
- codecs.iterdecode(iterator, encoding, errors='strict', **kwargs)¶
使用增量解码器迭代解码由 iterator 提供的输入。iterator 必须生成
bytes
对象。此函数是一个生成器。errors 参数(以及任何其他关键字参数)会传递给增量解码器。此函数要求编解码器接受
bytes
对象进行解码。因此,它不支持文本到文本的编码器,例如rot_13
,尽管rot_13
可以与iterencode()
等效使用。
- codecs.readbuffer_encode(buffer, errors=None, /)¶
返回一个
tuple
,其中包含 buffer(一个缓冲区兼容对象或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。
编解码器基类¶
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
对象的生命周期内切换不同的错误处理策略。errors 参数允许的值集可以通过
register_error()
进行扩展。- 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
(WORD JOINER
) 取代此角色)。尽管如此,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 函数实现,或以字典作为映射表。下表列出了按名称列出的编解码器,以及一些常用别名和可能使用该编码的语言。别名列表和语言列表均不旨在穷尽。请注意,大小写不同或使用连字符而不是下划线的拼写替代也是有效别名,因为它们在通过 normalize_encoding()
规范化后是等效的。例如,'utf-8'
是 'utf_8'
编解码器的有效别名。
备注
下表列出了最常见的别名,完整的列表请参阅源 aliases.py 文件。
在 Windows 上,所有代码页都提供 cpXXX
编解码器。但只有下表中列出的编解码器才保证在其他平台上存在。
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, 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, 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
的别名。
3.14 版本发生变化: 在 Windows 上,所有代码页现在都提供 cpXXX
编解码器。
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 带引号可打印。 |
|
uu_codec |
uu |
使用 uuencode 转换操作数。 |
|
zlib_codec |
zip, zlib |
使用 gzip 压缩操作数。 |
3.2 新增: 恢复了二进制转换。
3.4 版本发生变化: 恢复了二进制转换的别名。
独立编解码器函数¶
以下函数提供类似于编解码器的编码和解码功能,但不能通过 codecs.encode()
或 codecs.decode()
作为命名编解码器使用。它们在内部使用(例如,通过 pickle
),其行为类似于 Python 3 中已移除的 string_escape
编解码器。
文本转换¶
以下编解码器提供文本转换:str
到 str
的映射。它不支持 str.encode()
(它只生成 bytes
输出)。
编解码器 |
别名 |
含义 |
---|---|---|
rot_13 |
rot13 |
返回操作数的凯撒密码加密。 |
3.2 新增: 恢复了 rot_13
文本转换。
3.4 版本发生变化: 恢复了 rot13
别名。
encodings
— 编码包¶
本模块实现了以下函数
- encodings.normalize_encoding(encoding)¶
规范化编码名称 encoding。
规范化工作方式如下:除了用于 Python 包名的点之外,所有非字母数字字符都被折叠并替换为单个下划线,开头的和尾随的下划线被删除。例如,
' -;#'
变为'_'
。请注意,encoding 应仅包含 ASCII 字符。
备注
以下函数不应直接使用,除非用于测试目的;应改用 codecs.lookup()
。
- encodings.search_function(encoding)¶
搜索与给定编码名称 encoding 对应的编解码器模块。
此函数首先使用
normalize_encoding()
规范化 encoding,然后查找相应的别名。它尝试使用别名或规范化名称从 encodings 包中导入编解码器模块。如果找到模块并定义了有效的getregentry()
函数,该函数返回一个codecs.CodecInfo
对象,则编解码器将被缓存并返回。如果编解码器模块定义了
getaliases()
函数,则任何返回的别名都将注册以供将来使用。
- encodings.win32_code_page_search_function(encoding)¶
搜索
cpXXXX
形式的 Windows 代码页编码 encoding。如果代码页有效且受支持,则返回其
codecs.CodecInfo
对象。可用性: Windows。
在 3.14 版本加入。
本模块实现了以下异常
- exception encodings.CodecRegistryError¶
当编解码器无效或不兼容时引发。
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 的 nameprepped 版本。当前实现假定查询字符串,因此
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。