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

增量编码器和解码器类或工厂函数。这些必须分别提供由基类 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

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_BEBOM_UTF16_LEBOMBOM_UTF16 的别名,BOM_LEBOM_UTF16_LE 的别名,BOM_BEBOM_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 标准编码 编解码器

含义

'strict'

引发 UnicodeError(或其子类),这是默认值。在 strict_errors() 中实现。

'ignore'

忽略格式错误的数据并继续,不作进一步通知。在 ignore_errors() 中实现。

'replace'

替换为替换标记。编码时,使用 ?(ASCII 字符)。解码时,使用 (U+FFFD,官方替换字符)。在 replace_errors() 中实现。

'backslashreplace'

替换为反斜杠转义序列。编码时,使用 Unicode 码点的十六进制形式,格式为 \xhh \uxxxx \Uxxxxxxxx。解码时,使用字节值的十六进制形式,格式为 \xhh。在 backslashreplace_errors() 中实现。

'surrogateescape'

解码时,用范围从 U+DC80U+DCFF 的单个代理码替换字节。当编码数据时使用 'surrogateescape' 错误处理程序时,此代码将再次转换回相同的字节。(更多信息请参阅PEP 383。)

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

含义

'xmlcharrefreplace'

替换为 XML/HTML 数字字符引用,它是 Unicode 码点的十进制形式,格式为 &#num;。在 xmlcharrefreplace_errors() 中实现。

'namereplace'

替换为 \N{...} 转义序列,大括号中显示的是 Unicode 字符数据库中的名称属性。在 namereplace_errors() 中实现。

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

编解码器

含义

'surrogatepass'

utf-8, utf-16, utf-32, utf-16-be, utf-16-le, utf-32-be, utf-32-le

允许将代理码点(U+D800 - U+DFFF)作为普通码点进行编码和解码。否则,这些编解码器会将 str 中存在代理码点视为错误。

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,该实例包含有关错误位置的信息。错误处理程序必须要么引发此异常或不同的异常,要么返回一个元组,其中包含不可编码部分的替换以及编码应继续的位置。替换可以是 strbytes。如果替换是字节,则编码器将简单地将它们复制到输出缓冲区。如果替换是字符串,则编码器将编码替换。编码在指定位置的原始输入上继续。负位置值将被视为相对于输入字符串的末尾。如果生成的位置超出范围,则会引发 IndexError

解码和转换的工作方式类似,只是会将 UnicodeDecodeErrorUnicodeTranslateError 传递给处理程序,并且错误处理程序中的替换将直接放入输出中。

之前注册的错误处理程序(包括标准错误处理程序)可以通过名称查找

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 版中已更改: 适用于解码和转换。

codecs.xmlcharrefreplace_errors(exception)

实现 'xmlcharrefreplace' 错误处理(仅适用于文本编码中的编码)。

不可编码字符被替换为相应的 XML/HTML 数字字符引用,它是 Unicode 码点的十进制形式,格式为 &#num;

codecs.namereplace_errors(exception)

实现 'namereplace' 错误处理(仅适用于文本编码中的编码)。

不可编码字符被 \N{...} 转义序列替换。大括号中显示的字符集是 Unicode 字符数据库中的名称属性。例如,德语小写字母 'ß' 将转换为字节序列 \N{LATIN SMALL LETTER SHARP S}

在 3.5 版本加入。

无状态编码和解码

基类 Codec 定义了这些方法,它们也定义了无状态编码器和解码器的函数接口

class codecs.Codec
encode(input, errors='strict')

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

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

该方法可能不会在 Codec 实例中存储状态。对于必须保持状态以使编码高效的编解码器,请使用 StreamWriter

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

decode(input, errors='strict')

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

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

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

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

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

增量编码和解码

IncrementalEncoderIncrementalDecoder 类提供了增量编码和解码的基本接口。输入编码/解码不是通过一次调用无状态编码器/解码器函数完成的,而是通过对增量编码器/解码器的 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)

将编码器的状态设置为 statestate 必须是 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)

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

流编码和解码

StreamWriterStreamReader 类提供了通用的工作接口,可以非常容易地用于实现新的编码子模块。有关如何实现此功能的示例,请参阅 encodings.utf_8

StreamWriter 对象

StreamWriter 类是 Codec 的子类,并定义了每个流写入器必须定义的以下方法,以兼容 Python 编解码器注册表。

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

StreamWriter 实例的构造函数。

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

stream 参数必须是适用于特定编解码器的、用于写入文本或二进制数据的文件类对象。

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

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

write(object)

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

writelines(list)

将连接后的字符串可迭代对象写入流(可能通过重用 write() 方法)。不支持无限或非常大的可迭代对象。标准的字节到字节编解码器不支持此方法。

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 必须是文件类对象。ReaderWriter 必须是提供 StreamReaderStreamWriter 接口的工厂函数或类。错误处理方式与流读取器和写入器定义的方式相同。

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

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 类的组合接口。它们继承了底层流的所有其他方法和属性。

编码和 Unicode

字符串内部存储为代码点序列,范围为 U+0000U+10FFFF。(有关实现细节,请参阅PEP 393。)一旦字符串对象在 CPU 和内存之外使用,字节序以及这些数组如何存储为字节就成了问题。与其他编解码器一样,将字符串序列化为字节序列称为 编码,从字节序列重建字符串称为 解码。有各种不同的文本序列化编解码器,统称为文本编码

最简单的文本编码(称为 '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 还有第二个用途,即作为 零宽度不换行空格:一个没有宽度且不允许单词拆分的字符。例如,它可以用于给连字算法提供提示。根据 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 字符):

范围

编码

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 字符都被视为 零宽度不换行空格

在没有外部信息的情况下,不可能可靠地确定用于编码字符串的编码。每个字符映射编码都可以解码任何随机字节序列。但是,UTF-8 不可能做到这一点,因为 UTF-8 字节序列具有不允许任意字节序列的结构。为了提高 UTF-8 编码的检测可靠性,Microsoft 为其记事本程序发明了 UTF-8 的变体(Python 称之为 "utf-8-sig"):在任何 Unicode 字符写入文件之前,先写入一个 UTF-8 编码的 BOM(其字节序列为:0xef0xbb0xbf)。由于任何字符映射编码文件不太可能以这些字节值开头(例如,它们在 iso-8859-1 中会映射到

带分音符的拉丁小写字母 I
右指向双角引号
反问号

),这增加了从字节序列正确猜测 utf-8-sig 编码的可能性。因此,这里的 BOM 不是用来确定生成字节序列所使用的字节顺序,而是作为有助于猜测编码的签名。在编码时,utf-8-sig 编解码器将 0xef0xbb0xbf 作为前三个字节写入文件。在解码时,如果这些字节作为文件中的前三个字节出现,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+D800U+DFFF)。utf-32* 解码器不再解码对应于代理码点的字节序列。

3.8 版本发生变化: cp65001 现在是 utf_8 的别名。

3.14 版本发生变化: 在 Windows 上,所有代码页现在都提供 cpXXX 编解码器。

Python 特有编码

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

文本编码

以下编解码器提供 strbytes 的编码和 字节类对象str 的解码,类似于 Unicode 文本编码。

编解码器

别名

含义

idna

实现 RFC 3490,另请参阅 encodings.idna。仅支持 errors='strict'

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 编码,其中 \uXXXX\UXXXXXXXX 用于其他码点。现有的反斜杠不以任何方式转义。它用于 Python pickle 协议。

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(结果始终包含一个尾随 '\n')。

3.4 版本发生变化: 编码和解码接受任何 字节类对象 作为输入

base64.encodebytes() / base64.decodebytes()

bz2_codec

bz2

使用 bz2 压缩操作数。

bz2.compress() / bz2.decompress()

hex_codec

hex

将操作数转换为十六进制表示,每字节两位数字。

binascii.b2a_hex() / binascii.a2b_hex()

quopri_codec

quopri, quotedprintable, quoted_printable

将操作数转换为 MIME 带引号可打印。

quopri.encode() (带 quotetabs=True) / quopri.decode()

uu_codec

uu

使用 uuencode 转换操作数。

zlib_codec

zip, zlib

使用 gzip 压缩操作数。

zlib.compress() / zlib.decompress()

3.2 新增: 恢复了二进制转换。

3.4 版本发生变化: 恢复了二进制转换的别名。

独立编解码器函数

以下函数提供类似于编解码器的编码和解码功能,但不能通过 codecs.encode()codecs.decode() 作为命名编解码器使用。它们在内部使用(例如,通过 pickle),其行为类似于 Python 3 中已移除的 string_escape 编解码器。

codecs.escape_encode(input, errors=None)

使用转义序列编码 input。类似于 repr() 在字节上生成转义字节值的方式。

input 必须是 bytes 对象。

返回一个元组 (output, length),其中 output 是一个 bytes 对象,length 是已消耗的字节数。

codecs.escape_decode(input, errors=None)

input 从转义序列解码回原始字节。

input 必须是 字节类对象

返回一个元组 (output, length),其中 output 是一个 bytes 对象,length 是已消耗的字节数。

文本转换

以下编解码器提供文本转换:strstr 的映射。它不支持 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 5891RFC 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.clientftplib,接受 Unicode 主机名(如果 http.client 发送 Host 字段,它还会透明地在该字段中发送 IDNA 主机名)。

从网络接收主机名时(例如在反向名称查找中),不会自动转换为 Unicode:希望向用户呈现此类主机名的应用程序应将其解码为 Unicode。

encodings.idna 模块还实现了 nameprep 过程,该过程对主机名执行某些规范化,以实现国际域名的大小写不敏感,并统一相似字符。如果需要,可以直接使用 nameprep 函数。

encodings.idna.nameprep(label)

返回 label 的 nameprepped 版本。当前实现假定查询字符串,因此 AllowUnassigned 为 true。

encodings.idna.ToASCII(label)

将标签转换为 ASCII,如 RFC 3490 中指定。假定 UseSTD3ASCIIRules 为 false。

encodings.idna.ToUnicode(label)

将标签转换为 Unicode,如 RFC 3490 中指定。

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。