7.8. 编解码器—编解码器注册表和 Base Class

此模块为标准 Python 编解码器(编码器和解码器)定义 Base Class,并提供对内部 Python 编解码器注册表的访问,该注册表 Management 编解码器和错误处理查找过程。

它定义了以下Function:

  • codecs. encode(* obj * [,* encoding * [,* errors *]])
    • 使用为* encoding 注册的编解码器对 obj *进行编码。默认编码为'ascii'

错误可能会给您设置所需的错误处理方案。默认错误处理程序为'strict',这意味着编码错误会引发ValueError(或更特定于编解码器的子类,例如UnicodeEncodeError)。有关编解码器错误处理的更多信息,请参考编解码器 Base Class

2.4 版的新Function。

  • codecs. decode(* obj * [,* encoding * [,* errors *]])
    • 使用为* encoding 注册的编解码器对 obj *进行解码。默认编码为'ascii'

错误可能会给您设置所需的错误处理方案。默认错误处理程序为'strict',这意味着解码错误会引发ValueError(或更多特定于编解码器的子类,例如UnicodeDecodeError)。有关编解码器错误处理的更多信息,请参考编解码器 Base Class

2.4 版的新Function。

  • codecs. register(* search_function *)

    • 注册编解码器搜索Function。搜索函数应采用一个参数(所有小写字母的编码名称),并返回具有以下属性的CodecInfo对象:
  • name编码的名称;

  • encodeStateless 编码Function;

  • decodeStateless 解码Function;

  • incrementalencoder增量编码器类或工厂Function;

  • incrementaldecoder增量解码器类或工厂函数;

  • streamwriter流编写器类或工厂函数;

  • streamreader流读取器类或工厂Function。

各种函数或类采用以下参数:

  • encode decode *:这些必须是与编解码器实例的encode()/decode()方法具有相同接口的函数或方法(请参见Codec Interface)。这些Function/方法应该在 Stateless 模式下工作。

  • incrementalencoder incrementaldecoder *:这些必须是提供以下接口的工厂Function:

Note

factory(errors='strict')

工厂函数必须返回提供分别由 Base ClassIncrementalEncoderIncrementalDecoder定义的接口的对象。增量编解码器可以维持状态。

  • streamreader streamwriter *:这些必须是提供以下接口的工厂Function:

Note

factory(stream, errors='strict')

工厂函数必须返回提供分别由 Base ClassStreamReaderStreamWriter定义的接口的对象。流编解码器可以维护状态。

错误的可能值为

  • 'strict':在编码错误的情况下引发异常

  • 'replace':使用适当的替换标记(例如'?''\ufffd')替换格式错误的数据

  • 'ignore':忽略格式错误的数据,并 continue 进行操作,恕不另行通知

  • 'xmlcharrefreplace':替换为适当的 XML 字符引用(仅用于编码)

  • 'backslashreplace':替换为反斜杠转义序列(仅用于编码)

以及passregister_error()定义的任何其他错误处理名称。

如果搜索Function找不到给定的编码,则应返回None

  • codecs. lookup(编码)
    • 在 Python 编解码器注册表中查找编解码器信息,并返回上面定义的CodecInfo对象。

首先在注册表的缓存中查找编码。如果找不到,将扫描已注册的搜索Function列表。如果未找到CodecInfo对象,则引发LookupError。否则,CodecInfo对象将存储在缓存中并返回给调用方。

为了简化对各种编解码器的访问,该模块提供了以下附加Function,这些Function使用lookup()进行编解码器查找:

  • codecs. getencoder(编码)
    • 查找给定编码的编解码器,并返回其编码器Function。

如果找不到编码,则引发LookupError

  • codecs. getdecoder(编码)
    • 查找编解码器以获取给定的编码,然后返回其解码器Function。

如果找不到编码,则引发LookupError

  • codecs. getincrementalencoder(编码)
    • 查找给定编码的编解码器,并返回其增量编码器类或工厂Function。

如果找不到编码或编解码器不支持增量编码器,则引发LookupError

2.5 版的新Function。

  • codecs. getincrementaldecoder(编码)
    • 查找给定编码的编解码器,并返回其增量解码器类或工厂函数。

在找不到编码或编解码器不支持增量解码器的情况下引发LookupError

2.5 版的新Function。

  • codecs. getreader(编码)
    • 查找给定编码的编解码器,并返回其 StreamReader 类或工厂函数。

如果找不到编码,则引发LookupError

  • codecs. getwriter(编码)
    • 查找给定编码的编解码器,并返回其 StreamWriter 类或工厂函数。

如果找不到编码,则引发LookupError

  • codecs. register_error(* name error_handler *)
    • 在名称* name 下注册错误处理函数 error_handler 。如果将 name 指定为 errors 参数,则在编码和解码过程中如果发生错误,将调用 error_handler *。

为了进行编码,将使用UnicodeEncodeError实例调用* error_handler *,该实例包含有关错误位置的信息。错误处理程序必须引发此异常或不同的异常,或者返回一个 Tuples,并替换 Importing 中无法编码的部分以及应 continue 编码的位置。编码器将对替换进行编码,并 continue 在指定位置编码原始 Importing。负位置值将被视为相对于 Importing 字符串的末尾。如果结果位置超出范围,则将引发IndexError

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

  • codecs. lookup_error(* name *)
    • 返回先前以名称* name *注册的错误处理程序。

引发LookupError以防找不到处理程序。

  • codecs. strict_errors(* exception *)

    • 实现strict错误处理:每个编码或解码错误都会引发UnicodeError
  • codecs. replace_errors(* exception *)

    • 实现replace错误处理:格式错误的数据将替换为合适的替换字符,例如字节字符串中的'?'和 Unicode 字符串中的'\ufffd'
  • codecs. ignore_errors(* exception *)

    • 实现ignore错误处理:格式错误的数据将被忽略,并且 continue 进行编码或解码,恕不另行通知。
  • codecs. xmlcharrefreplace_errors(* exception *)

    • 实现xmlcharrefreplace错误处理(仅用于编码):无法编码的字符由适当的 XML 字符引用代替。
  • codecs. backslashreplace_errors(* exception *)

    • 实现backslashreplace错误处理(仅用于编码):无法编码的字符由反斜杠转义序列代替。

为了简化编码文件或流的处理,该模块还定义了以下 Util Function:

  • codecs. open(文件名模式 [,编码 [,错误 [,缓冲]]])
    • 使用给定的* mode *打开编码的文件,并返回提供透明编码/解码的包装版本。默认文件模式为'r',表示以读取模式打开文件。

Note

包装版本仅接受编解码器定义的对象格式,即大多数内置编解码器的 Unicode 对象。输出还取决于编解码器,通常也将是 Unicode。

Note

即使未指定二进制模式,文件也始终以二进制模式打开。这样做是为了避免由于使用 8 位值进行编码而导致的数据丢失。这意味着在读写时不会自动进行'\n'的转换。

  • encoding *指定将用于文件的编码。

可以给出* errors *来定义错误处理。默认为'strict',如果发生编码错误,则会引发ValueError

  • buffering *具有与内置open()函数相同的含义。默认为行缓冲。
  • codecs. EncodedFile(* file input * [,* output * [,* errors *]])
    • 返回提供透明编码转换的文件的包装版本。

写入包装文件的字符串将根据给定的* input 编码进行解释,然后使用 output *编码作为字符串写入原始文件。中间编码通常为 Unicode,但取决于指定的编解码器。

如果未提供* output ,则默认为 input *。

可以给出* errors *来定义错误处理。默认为'strict',如果发生编码错误,则会导致ValueError升高。

  • codecs. iterencode(* iterable encoding * [,* errors *])
    • 使用增量编码器对* iterable *提供的 Importing 进行迭代编码。此函数是generator错误(以及任何其他关键字参数)被传递到增量编码器。

2.5 版的新Function。

  • codecs. iterdecode(* iterable encoding * [,* errors *])
    • 使用增量解码器对* iterable *提供的 Importing 进行迭代解码。此函数是generator错误(以及任何其他关键字参数)被传递到增量解码器。

2.5 版的新Function。

该模块还提供以下常量,这些常量对于读取和写入依赖于平台的文件非常有用:

  • 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
    • 这些常量定义在 UTF-16 和 UTF-32 数据流中使用的 Unicode 字节 Sequences 标记(BOM)的各种编码,以指示在流或文件中以及在 UTF-8 中用作 Unicode 签名的字节 Sequences。 BOM_UTF16BOM_UTF16_BEBOM_UTF16_LE,具体取决于平台的本机字节 Sequences,BOMBOM_UTF16的别名,BOM_LEBOM_UTF16_LE的别名,而BOM_BEBOM_UTF16_BE的别名。其他代表 UTF-8 和 UTF-32 编码的 BOM。

7.8.1. 编解码器 Base Class

codecs模块定义了一组 Base Class,这些 Base Class 定义了接口,还可以用于轻松编写自己的编解码器以用于 Python。

每个编解码器必须定义四个接口以使其在 Python 中可用作编解码器:Stateless 编码器,Stateless 解码器,流读取器和流写入器。流读取器和写入器通常重用 Stateless 编码器/解码器以实现文件协议。

Codec类定义了 Stateless 编码器/解码器的接口。

为了简化和标准化错误处理,encode()decode()方法可以pass提供* errors *字符串参数来实现不同的错误处理方案。以下字符串值由所有标准 Python 编解码器定义和实现:

ValueMeaning
'strict'提高UnicodeError(或子类);这是默认值。
'ignore'忽略字符并 continue 下一个。
'replace'用合适的替换字符替换; Python 将对解码和'?'使用内置的 Unicode 编解码器的官方 U FFFD REPLACEMENT CHARACTER 关于编码。
'xmlcharrefreplace'替换为适当的 XML 字符引用(仅用于编码)。
'backslashreplace'替换为反斜杠转义序列(仅用于编码)。

允许值的集合可以passregister_error()扩展。

7.8.1.1. 编解码器对象

Codec类定义了这些方法,这些方法还定义了 Stateless 编码器和解码器的Function接口:

  • Codec. encode(* input * [,* errors *])
    • 对对象* input *进行编码,并返回一个 Tuples(输出对象,使用的长度)。虽然编解码器不限于与 Unicode 一起使用,但在 Unicode 上下文中,编码使用特定的字符集编码(例如cp1252iso-8859-1)将 Unicode 对象转换为纯字符串。
  • errors *定义要应用的错误处理。默认为'strict'处理。

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

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

  • Codec. decode(* input * [,* errors *])
    • 解码对象* input *并返回一个 Tuples(输出对象,消耗的长度)。在 Unicode 上下文中,解码会将使用特定字符集编码编码的纯字符串转换为 Unicode 对象。
  • input *必须是提供bf_getreadbuf缓冲区插槽的对象。 Python 字符串,缓冲区对象和内存 Map 文件是提供此插槽的对象的示例。

  • errors *定义要应用的错误处理。默认为'strict'处理。

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

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

IncrementalEncoderIncrementalDecoder类提供用于增量编码和解码的基本接口。Importing 的编码/解码不是pass一次调用 Stateless 编码器/解码器函数来完成的,而是pass多次调用增量式编码器/解码器的encode()/decode()方法来完成的。增量编码器/解码器在方法调用期间跟踪编码/解码过程。

encode()/decode()方法的调用的合并输出与将所有单个 Importing 合并为一个相同,并且使用 Stateless 编码器/解码器对该 Importing 进行编码/解码。

7.8.1.2. 增量编码器对象

2.5 版的新Function。

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

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

IncrementalEncoder可以pass提供* errors *关键字参数来实现不同的错误处理方案。这些参数是 sched 义的:

  • 'strict'提高ValueError(或子类);这是默认值。

  • 'ignore'忽略该字符,然后 continue 下一个。

  • 'replace'用合适的替换字符替换

  • 'xmlcharrefreplace'替换为适当的 XML 字符引用

  • 'backslashreplace'替换为反斜杠转义序列。

  • errors *参数将分配给相同名称的属性。分配给该属性可以在IncrementalEncoder对象的生存期内在不同的错误处理策略之间进行切换。

可以使用register_error()扩展* errors *参数的允许值集。

  • encode(* object * [,* final *])

    • 对* object *进行编码(考虑编码器的当前状态),然后返回生成的编码对象。如果这是对encode() * final *的最后一次调用,则必须为 true(默认值为 false)。
  • reset ( )

    • 将编码器重置为初始状态。

7.8.1.3. 增量解码器对象

IncrementalDecoder类用于多步解码 Importing。它定义了每个增量解码器都必须定义的以下方法,以便与 Python 编解码器注册表兼容。

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

IncrementalDecoder可以pass提供* errors *关键字参数来实现不同的错误处理方案。这些参数是 sched 义的:

  • 'strict'提高ValueError(或子类);这是默认值。

  • 'ignore'忽略该字符,然后 continue 下一个。

  • 'replace'用合适的替换字符替换。

  • errors *参数将分配给相同名称的属性。分配给该属性可以在IncrementalDecoder对象的生存期内在不同的错误处理策略之间进行切换。

可以使用register_error()扩展* errors *参数的允许值集。

  • decode(* object * [,* final *])

    • 解码* object *(考虑解码器的当前状态)并返回生成的解码对象。如果这是对decode() * final 的最后一次调用,则必须为 true(默认值为 false)。如果 final *为 true,则解码器必须完全解码 Importing,并且必须刷新所有缓冲区。如果这是不可能的(例如由于 Importing 末尾的字节序列不完整),则它必须像在 Stateless 情况下(可能会引发异常)一样启动错误处理。
  • reset ( )

    • 将解码器重置为初始状态。

StreamWriterStreamReader类提供了通用的工作接口,可用于非常轻松地实现新的编码子模块。有关执行此操作的示例,请参见encodings.utf_8

7.8.1.4. StreamWriter 对象

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

    • class * codecs. StreamWriter(* stream * [,* errors *])

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

  • stream *必须是打开的用于写入二进制数据的类似文件的对象。

StreamWriter可以pass提供* errors *关键字参数来实现不同的错误处理方案。这些参数是 sched 义的:

  • 'strict'提高ValueError(或子类);这是默认值。

  • 'ignore'忽略该字符,然后 continue 下一个。

  • 'replace'用合适的替换字符替换

  • 'xmlcharrefreplace'替换为适当的 XML 字符引用

  • 'backslashreplace'替换为反斜杠转义序列。

  • errors *参数将分配给相同名称的属性。分配给该属性可以在StreamWriter对象的生存期内在不同的错误处理策略之间进行切换。

可以使用register_error()扩展* errors *参数的允许值集。

  • write(* object *)

    • 将编码后的对象的内容写入流中。
  • writelines(列表)

    • 将字符串的串联列表写入流中(可能pass重用write()方法)。
  • reset ( )

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

调用此方法应确保将输出上的数据置于干净状态,该状态允许附加新的新数据,而不必重新扫描整个流以恢复状态。

除上述方法外,StreamWriter还必须从基础流继承所有其他方法和属性。

7.8.1.5. StreamReader 对象

StreamReader类是Codec的子类,它定义以下方法,每个流读取器都必须定义以下方法,以便与 Python 编解码器注册表兼容。

    • class * codecs. StreamReader(* stream * [,* errors *])

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

  • stream *必须是打开的用于读取(二进制)数据的类似文件的对象。

StreamReader可以pass提供* errors *关键字参数来实现不同的错误处理方案。定义了这些参数:

  • 'strict'提高ValueError(或子类);这是默认值。

  • 'ignore'忽略该字符,然后 continue 下一个。

  • 'replace'用合适的替换字符替换。

  • errors *参数将分配给相同名称的属性。分配给该属性可以在StreamReader对象的生存期内在不同的错误处理策略之间进行切换。

可以使用register_error()扩展* errors *参数的允许值集。

  • read([[* size * [,* chars * [,* firstline *]]])
    • 从流中解码数据并返回结果对象。
  • chars 表示要从流中读取的字符数。 read()绝不会返回超过个字符的字符,但是如果没有足够的可用字符,则返回的字符数可能会更少。

  • size *表示要从流中读取以进行解码的大概最大字节数。解码器可以适当修改此设置。默认值-1 表示要尽可能多地读取和解码。 * size *旨在避免必须一步解码大型文件。

  • firstline *表示如果后面的行中有解码错误,仅返回第一行就足够了。

该方法应使用贪婪读取策略,这意味着它应读取编码定义和给定大小(例如,如果流上有可选的编码结尾或状态标记,则也应读取它们。

在版本 2.4 中更改:添加了* chars *参数。

在版本 2.4.2 中更改:添加了* firstline *参数。

  • readline([[* size * [,* keepends *]])
    • 从 Importing 流中读取一行并返回解码后的数据。
  • size *(如果给定的话)作为 size 参数传递给流的read()方法。

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

在版本 2.4 中更改:添加了* keepends *参数。

  • readlines([* sizehint * [,* keepends *]])
    • 读取 Importing 流上所有可用的行,并将它们作为行列表返回。

行尾使用编解码器的解码器方法实现,并且如果* keepends *为 true,则将其包括在列表条目中。

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

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

请注意,不应进行流重新定位。该方法主要旨在能够从解码错误中恢复。

除上述方法外,StreamReader还必须从基础流继承所有其他方法和属性。

为方便起见,包括了以下两个基本类。编解码器注册表不需要它们,但实际上它们可能有用。

7.8.1.6. StreamReaderWriter 对象

StreamReaderWriter允许包装可在读取和写入模式下工作的流。

这种设计使得可以使用lookup()函数返回的工厂函数来构造实例。

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

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

7.8.1.7. StreamRecoder 对象

StreamRecoder提供了编码数据的前端-后端视图,该视图有时在处理不同的编码环境时很有用。

这种设计使得可以使用lookup()函数返回的工厂函数来构造实例。

    • class * codecs. StreamRecoder(* stream encode decode Reader Writer errors *)
    • 创建一个实现双向转换的StreamRecoder实例:* encode decode 在前端(read()的 Importing 和write()的输出)工作,而 Reader Writer *在后端(读取和写入数据)工作流)。

您可以使用这些对象进行透明的直接重新编码,例如 Latin-1 转换为 UTF-8,然后返回。

  • stream *必须是类似文件的对象。

  • encode decode *必须遵守Codec接口。 * Reader Writer *必须是工厂函数或提供分别为StreamReaderStreamWriter接口的对象的类。

前端翻译需要* encode decode ,后端翻译需要 Reader Writer *。所使用的中间格式由两组编解码器确定,例如 Unicode 编解码器将使用 Unicode 作为中间编码。

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

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

7.8.2. 编码和 Unicode

Unicode 字符串在内部存储为代码点序列(准确地说是Py_UNICODE数组)。取决于 python 的编译方式(pass--enable-unicode=ucs2--enable-unicode=ucs4,默认为前者)Py_UNICODE是 16 位或 32 位数据类型。一旦在 CPU 和内存之外使用了 Unicode 对象,CPU 字节 Sequences 以及如何将这些数组存储为字节就成为问题。将 unicode 对象转换为字节序列称为编码,从该字节序列重新创建 unicode 对象称为解码。如何完成此转换的方法有很多(这些方法也称为编码)。最简单的方法是将代码点 0–255Map 到字节0x00xff。这意味着包含U+00FF以上代码点的 unicode 对象无法使用此方法(称为'latin-1''iso-8859-1')进行编码。 unicode.encode()将引发一个UnicodeEncodeError,如下所示:UnicodeEncodeError: 'latin-1' codec can't encode character u'\u1234' in position 3: ordinal not in range(256)

还有另一组编码(所谓的 charmap 编码),它们选择所有 unicode 代码点的不同子集,以及如何将这些代码点 Map 到字节0x00xff。要查看如何完成此操作,只需打开例如encodings/cp1252.py(这是主要在 Windows 上使用的编码)。有一个包含 256 个字符的字符串常量,向您显示哪个字符 Map 到哪个字节值。

所有这些编码只能编码 Unicode 中定义的 1114112 个代码点中的 256 个。可以存储每个 Unicode 代码点的一种简单明了的方法是将每个代码点存储为四个连续的字节。有两种可能性:以大字节序或小字节序存储字节。这两种编码分别称为UTF-32-BEUTF-32-LE。它们的缺点是例如您在小型字节序计算机上使用UTF-32-BE,则始终必须在编码和解码时交换字节。 UTF-32避免了此问题:字节将始终保持自然字节序。当这些字节由具有不同字节序的 CPU 读取时,则必须交换字节。为了能够检测到UTF-16UTF-32字节序列的字节序,有所谓的 BOM(“字节 Sequences 标记”)。这是 Unicode 字符U+FEFF。可以在每个UTF-16UTF-32字节序列之前添加此字符。此字符的字节交换版本(0xFFFE)是非法字符,可能不会出现在 Unicode 文本中。因此,当UTF-16UTF-32字节序列中的第一个字符显示为U+FFFE时,必须在解码时交换字节。不幸的是,字符U+FEFF具有第二个目的,即ZERO WIDTH NO-BREAK SPACE:该字符没有宽度并且不允许拆分单词。它可以例如用于提示连字算法。在使用U+FEFF作为ZERO WIDTH NO-BREAK SPACE的 Unicode 4.0 中,已弃用(使用U+2060(WORD JOINER)担任此角色)。但是,Unicode 软件仍然必须能够同时扮演U+FEFF的角色:作为 BOM,它是一种确定编码字节存储布局的设备,一旦字节序列被解码为 Unicode 字符串,它便消失了;作为ZERO WIDTH NO-BREAK SPACE,它是正常字符,将像其他字符一样被解码。

还有另一种能够对所有 Unicode 字符进行编码的编码:UTF-8. UTF-8 是 8 位编码,这意味着 UTF-8 中的字节 Sequences 没有问题。 UTF-8 字节序列中的每个字节都由两部分组成:标记位(最高有效位)和有效载荷位。标记位是从零到四个1位,然后是0位的序列。 Unicode 字符的编码是这样的(x 是有效载荷位,当连接时会给出 Unicode 字符):

RangeEncoding
U-00000000U-0000007F0xxxxxxx
U-00000080U-000007FF110xxxxx 10xxxxxx
U-00000800U-0000FFFF1110 xxxx 10xxxxxx 10xxxxxx
U-00010000U-0010FFFF11110 xxx 10xxxxxx 10xxxxxx 10xxxxxx

Unicode 字符的最低有效位是最右边的 x 位。

由于 UTF-8 是 8 位编码,因此不需要 BOM,并且解码的 Unicode 字符串中的任何U+FEFF字符(即使它是第一个字符)也被视为ZERO WIDTH NO-BREAK SPACE

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

Note

带有拉丁文的拉丁文小写字母 I

正确的双角引号

反问号

在 iso-8859-1 中),这增加了从字节序列中正确猜出utf-8-sig编码的可能性。因此,这里的 BOM 不是用来确定用于生成字节序列的字节 Sequences,而是作为有助于猜测编码的签名。在对 utf-8-sig 编解码器进行编码时,会将0xef0xbb0xbf作为前三个字节写入文件。在解码utf-8-sig时,如果这三个字节显示为文件中的前三个字节,则会跳过这三个字节。在 UTF-8 中,不建议使用 BOM,通常应避免使用 BOM。

7.8.3. 标准编码

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

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

  • ISO 8859 代码集

  • Microsoft Windows 代码页,通常从 8859 代码集派生,但是将控制字符替换为其他图形字符

  • IBM EBCDIC 代码页

  • IBM PC 代码页,它与 ASCII 兼容

CodecAliasesLanguages
ascii646, us-asciiEnglish
big5big5-tw, csbig5Traditional Chinese
big5hkscsbig5-hkscs, hkscsTraditional Chinese
cp037IBM037, IBM039English
cp424EBCDIC-CP-HE, IBM424Hebrew
cp437437, IBM437English
cp500EBCDIC-CP-BE,EBCDIC-CP-CH,IBM500Western Europe
cp720Arabic
cp737Greek
cp775IBM775Baltic languages
cp850850, IBM850Western Europe
cp852852, IBM852中欧和东欧
cp855855, IBM855保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语
cp856Hebrew
cp857857, IBM857Turkish
cp858858, IBM858Western Europe
cp860860, IBM860Portuguese
cp861861,CP-IS,IBM861Icelandic
cp862862, IBM862Hebrew
cp863863, IBM863Canadian
cp864IBM864Arabic
cp865865, IBM865Danish, Norwegian
cp866866, IBM866Russian
cp869869,CP-GR,IBM869Greek
cp874Thai
cp875Greek
cp932932,ms932,mskanji,ms-kanjiJapanese
cp949949,ms949,uhcKorean
cp950950, ms950Traditional Chinese
cp1006Urdu
cp1026ibm1026Turkish
cp1140ibm1140Western Europe
cp1250windows-1250中欧和东欧
cp1251windows-1251保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语
cp1252windows-1252Western Europe
cp1253windows-1253Greek
cp1254windows-1254Turkish
cp1255windows-1255Hebrew
cp1256windows-1256Arabic
cp1257windows-1257Baltic languages
cp1258windows-1258Vietnamese
euc_jpeucjp,ujis,u-jisJapanese
euc_jis_2004jisx0213, eucjis2004Japanese
euc_jisx0213eucjisx0213Japanese
euc_kreuckr,韩文,ksc5601,ks_c-5601,ks_c-5601-1987,ksx1001,ks_x-1001Korean
gb2312中文,csiso58gb231280,euc- cn,euccn,eucgb2312-cn,gb2312-1980,gb2312-80,iso-ir-58Simplified Chinese
gbk936,cp936,ms936Unified Chinese
gb18030gb18030-2000Unified Chinese
hzhzgb,hz-gb,hz-gb-2312Simplified Chinese
iso2022_jpcsiso2022jp,iso2022jp,iso-2022-jpJapanese
iso2022_jp_1iso2022jp-1, iso-2022-jp-1Japanese
iso2022_jp_2iso2022jp-2, iso-2022-jp-2日文,韩文,简体中文,西欧,希腊文
iso2022_jp_2004iso2022jp-2004, iso-2022-jp-2004Japanese
iso2022_jp_3iso2022jp-3, iso-2022-jp-3Japanese
iso2022_jp_extiso2022jp-ext, iso-2022-jp-extJapanese
iso2022_krcsiso2022kr,iso2022kr,iso-2022-krKorean
latin_1iso-8859-1,iso8859-1、8859,cp819,拉丁语,latin1,L1West Europe
iso8859_2iso-8859-2,latin2,L2中欧和东欧
iso8859_3iso-8859-3,latin3,L3Esperanto, Maltese
iso8859_4iso-8859-4,latin4,L4Baltic languages
iso8859_5iso-8859-5, cyrillic保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语
iso8859_6iso-8859-6, arabicArabic
iso8859_7iso-8859-7,希腊,希腊 8Greek
iso8859_8iso-8859-8, hebrewHebrew
iso8859_9iso-8859-9,latin5,L5Turkish
iso8859_10iso-8859-10,latin6,L6Nordic languages
iso8859_11iso-8859-11, thaiThai languages
iso8859_13iso-8859-13,latin7,L7Baltic languages
iso8859_14iso-8859-14,latin8,L8Celtic languages
iso8859_15iso-8859-15,latin9,L9Western Europe
iso8859_16iso-8859-16,latin10,L10South-Eastern Europe
johabcp1361, ms1361Korean
koi8_rRussian
koi8_uUkrainian
mac_cyrillicmaccyrillic保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语
mac_greekmacgreekGreek
mac_icelandmacicelandIcelandic
mac_latin2maclatin2, maccentraleurope中欧和东欧
mac_romanmacromanWestern Europe
mac_turkishmacturkishTurkish
ptcp154csptcp154,pt154,cp154,西里尔字母亚洲Kazakh
shift_jiscsshiftjis,shiftjis,sjis,s_jisJapanese
shift_jis_2004shiftjis2004,sjis_2004,sjis2004Japanese
shift_jisx0213shiftjisx0213,sjisx0213,s_jisx0213Japanese
utf_32U32, utf32all languages
utf_32_beUTF-32BEall languages
utf_32_leUTF-32LEall languages
utf_16U16, utf16all languages
utf_16_beUTF-16BE所有语言(仅 BMP)
utf_16_leUTF-16LE所有语言(仅 BMP)
utf_7U7, unicode-1-1-utf-7all languages
utf_8U8,UTF,utf8all languages
utf_8_sigall languages

7.8.4. 特定于 Python 的编码

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

与 Unicode 文本编码类似,以下编解码器提供 unicode-to-str 编码[1]和 str-to-unicode 解码[2]

CodecAliasesPurpose
idna实现 RFC 3490,另请参见encodings.idna
mbcsdbcs仅限 Windows:根据 ANSI 代码页(CP_ACP)编码操作数
palmosPalmOS 3.5 的编码
punycodeImplements RFC 3492
raw_unicode_escape产生一个适合作为 Python 源代码中的原始 UnicodeLiterals 的字符串
rot_13rot13返回操作数的凯撒密码加密
undefined为所有转化引发 exception。如果不需要字节和 Unicode 字符串之间的自动coercion,则可以用作系统编码。
unicode_escape产生一个适合作为 Python 源代码中的 UnicodeLiterals 的字符串
unicode_internal返回操作数的内部表示

2.3 版中的新Function:idnapunycode编码。

以下编解码器提供 str 到 str 的编码和解码[2]

CodecAliasesPurposeEncoder/decoder
base64_codecbase64, base-64将操作数转换为多行 MIME base64(结果始终包含结尾的'\n')base64.encodestring(), base64.decodestring()
bz2_codecbz2使用 bz2 压缩操作数bz2.compress(), bz2.decompress()
hex_codechex将操作数转换为十六进制表示,每字节两位binascii.b2a_hex(), binascii.a2b_hex()
quopri_codecquopri,加引号可打印,加引号可打印将操作数转换为 MIME 引用可打印的内容quopri.encode()quotetabs=Truequopri.decode()
string_escape产生一个适合作为 Python 源代码中的字符串 Literals 的字符串
uu_codecuu使用 uuencode 转换操作数uu.encode(), uu.decode()
zlib_codeczip, zlib使用 gzip 压缩操作数zlib.compress(), zlib.decompress()
  • [1]

    • 也可以使用 str 对象代替 unicode 对象作为 Importing。pass使用默认编码对它们进行解码,可以将它们隐式转换为 unicode。如果此转换失败,则可能导致编码操作提高UnicodeDecodeError
  • 2 (1,2)

    • 代替 str 对象,也可以将 unicode 对象作为 Importing。pass使用默认编码对它们进行编码,可以将它们隐式转换为 str。如果此转换失败,则可能导致解码操作提高UnicodeEncodeError

7.8.5. encodings.idna —应用程序中的国际化域名

2.3 版的新Function。

此模块实现 RFC 3490(应用程序中的国际化域名)和 RFC 3492(Nameprep:国际化域名(IDN)的 Stringprep 配置文件)。它基于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 3490section 3.1(1)中定义的分隔符将 Importing 字符串分离为标签,并根据需要将每个标签转换为 ACE,然后反之根据.分隔符将 Importing 字节字符串转换为标签,并将找到的所有 ACE 标签转换为 unicode。此外,socket模块将 Unicode 主机名透明地转换为 ACE,因此在将主机名传递给套接字模块时,应用程序不必担心转换主机名本身。最重要的是,将具有主机名作为Function参数的模块(例如httplibftplib)接受 Unicode 主机名(httplib然后也可以在* Host *字段中透明地发送 IDNA 主机名(如果它完全发送该字段)。

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

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

  • encodings.idna. nameprep(* label *)

    • 返回* label *的名称准备版本。该实现当前采用查询字符串,因此AllowUnassigned为 true。
  • encodings.idna. ToASCII(* label *)

    • 按照 RFC 3490的指定将标签转换为 ASCII。 UseSTD3ASCIIRules假定为假。
  • encodings.idna. ToUnicode(* label *)

    • 按照 RFC 3490中的指定将标签转换为 Unicode。

7.8.6. encodings.utf_8_sig —具有 BOM 表签名的 UTF-8 编解码器

2.5 版的新Function。

该模块实现了 UTF-8 编解码器的一种变体:在编码时,UTF-8 编码的 BOM 将前置于 UTF-8 编码的字节。对于有状态编码器,此操作仅执行一次(第一次写入字节流时)。为了对数据开头的可选 UTF-8 编码 BOM 进行解码,将被跳过。