Python 2.3中引入源文件编码声明的PEP历史与Unicode文字解释增强

马尔在 lemburg.com ,这里的“lemburg.com”指的是马克·安德烈·伦伯格;马丁在 v.loewis.de ,这里的“v.loewis.de”指的是马丁·冯·洛维斯。

Python 2.3中引入源文件编码声明的PEP历史与Unicode文字解释增强

状态:

最后

类型:

标准跟踪

创建时间:

2001年6月6日

Python版本:

2.3

历史后:

内容

该 PEP 建议引入一种语法,目的是声明 Python 源文件的编码。接着,Python 解析器会依据编码信息,使用给定的编码去解释文件。尤其值得注意的是,这使得源代码中 Unicode 文字的解释得到了增强,并且能够在像 Unicode 这样的编辑器中直接使用 UTF-8 来编写 Unicode 文字。

在 Python 2.1 里,仅能使用以 Latin-1 为基础的编码“unicode-escape”来编写 Unicode 文字。这就让编程环境对那些在许多亚洲国家/地区之外的、处于非 Latin-1 语言环境中生活和工作的 Python 用户来说,是相当不利的。程序员能够用自己最喜欢的编码去编写其 8 位字符串。然而,存在一种绑定到 Unicode 文字的“unicode-escape”编码。

我建议通过在文件的顶部使用特殊注释来声明该编码,这样每个源文件就能够看到并且更改 Python 源代码的编码。

要让 Python 知晓此编码声明,在处理 Python 源代码数据时需要做出一些概念性的改变。

Python 在没有其他编码提示的情况下,会默认将 ASCII 作为标准编码。

定义源代码编码时,需要把魔术注释放置在源文件的第一行或第二行。比如:

#coding = <编码名称>

或(使用流行的编辑器认可的格式):

#!/ usr / bin / python
#-*-编码:<编码名称>-*-

要么:

#!/ usr / bin / python
#vim:设置fileencoding = <编码名称>:

更准确地说,第一行或第二行必须匹配以下正则表达式:

[ \ t \ f] *#。*?其编码[:=] [ \ t] *(由[-_。a-zA-Z0-9]组成)

首先将此表达式的第一组解释为编码名称。倘若 Python 不了解该编码,那么在编译期间就会引发错误。在包含编码声明的那一行上,不能有任何 Python 语句。要是第一行相匹配,第二行就会被忽略。

该平台为帮助诸如 Windows 之类的平台,在 Unicode 文件开头添加了 Unicode BOM 标记。同时,UTF - 8 签名\ xef \ xbb \ xbf 也会被解释为“utf - 8”编码,即便没有魔术编码注释也是如此。

如果源文件使用了 UTF-8 BOM 标记签名,并且也使用了魔术编码注释,那么注释所允许的唯一编码就是'utf-8'。其他任何编码都会引发错误。

3. 还有其他定义编码的样式可供参考。

使用解释器二进制文件并使用Emacs样式文件编码注释:

#!/ usr / bin / python
#-*-编码:latin-1-*-
导入操作系统
...
#!/ usr / bin / python
#-*-编码:iso-8859-15-*-
导入操作系统
...
#!/ usr / bin / python
#-*-编码:ascii-*-
导入操作系统
...

没有解释器行,使用纯文本:

#此Python文件使用以下编码:utf-8
导入操作系统
...

文本编辑器可能以不同的方式定义文件的编码,例如:

/usr/local/bin/python 这个路径所对应的程序被使用到了。它可能是用于执行特定的 Python 脚本或进行相关的 Python 操作。
#编码:latin-1
导入操作系统
...

没有编码注释,Python的解析器将采用ASCII文本:

#!/ usr / local / bin / python
导入操作系统
...

编码无效的注释:

缺少“ coding:”前缀:

#!/ usr / local / bin / python
#latin-1
导入操作系统
...

不在第1行或第2行上编码注释

#!/ usr / local / bin / python
#
#-*-编码:latin-1-*-
导入操作系统
...

不支持的编码:

#!/ usr / local / bin / python
#-*-编码:utf-42-*-
导入操作系统
...

PEP基于以下概念,必须实现这些概念才能使用这种魔术注释:

完整的 Python 源文件需使用单一编码。不可以嵌入不同编码的数据,因为在编译 Python 源代码时会引发解码错误。

可以用作源代码编码的方式包括处理前两行的任何编码,这些编码包含 ASCII 兼容编码以及某些多字节编码,像 Shift_JIS 。而像 UTF-16 这种对所有字符使用两个或多个字节的编码不在此列。这样做是为了让令牌检测器中的编码检测算法保持简单。

转义序列的处理要继续像现在这样工作。要使用所有可能的源代码编码,也就是标准字符串文字(包括 8 位和 Unicode)都能够进行转义序列扩展。而原始字符串文字仅仅能扩展很小的子集转义序列。

Python 的 tokenizer 和 compiler 组合需要进行更新,使其能够按照以下方式进行工作:

读取文件时假设每一个文件有固定编码,先将其解码为 Unicode,接着把它转换为 UTF-8 字节字符串,然后对 UTF-8 内容进行标记化,之后根据给定的 Unicode 数据创建 Unicode 对象,并且根据 Unicode 文字数据创建字符串对象,具体做法是先用给定的文件编码将 UTF-8 数据重新编码为 8 位字符串数据。

请注意,Python 的标识符只在编码的 ASCII 子集中。所以在步骤 4 之后,就不需要再进行转换了。

该代码当前在字符串文字中使用非 ASCII 且未声明编码,这是为了与现有代码向后兼容。所以将分两个阶段来介绍该实现。

内部将缺少的编码声明视为“iso-8859-1”声明,这样就可以在字符串文字和注释中使用非 ASCII 。这会使得任意字节字符串在处理的步骤 2 和步骤 5 之间能正确地往返,并且能为包含非 ASCII 字节的 Unicode 文字提供与 Python 2.2 的兼容性。

如果输入中存在非 ASCII 字节,那么就会针对每一个编码不正确的输入文件发送一次警告。

删除警告,并将默认编码更改为“ ascii”。

内置的 compile()API 会被增强,能够接受 Unicode 作为输入。并且,如前文所述,8 位字符串输入必须要经过编码检测的标准流程。

将带有编码声明的 Unicode 字符串传递给 compile()的话,就会引发 SyntaxError。

SUZUKI Hisao正在进行补丁的制作。若想了解详细信息,请进行查看。已经提供了仅能实现阶段 1 的补丁。

上面的步骤 1 以及步骤 2 的实现是在 2.3 中完成的,并且将默认编码改成了“ascii”。

在版本2.5中,默认编码设置为“ ascii”。

该 PEP 的目的是提供一条升级路径,从当前(在一定程度上)未明确界定的源代码编码状况,升级到更为健壮且可移植的定义。

你可能想看:
« 上一篇
下一篇 »

相关推荐

python爬虫教程PDF,Python爬虫书PDF

2026年09月02日

31阅读

外国教程python,python编程教学视频

2026年09月02日

25阅读

python简明教程沈洁元,python详细基础教程

2026年09月02日

21阅读

python库包教程,python 包

2026年09月02日

27阅读

python教程大全集,python教程600集

2026年09月02日

26阅读

python入门教程完整版,python零基础入门全套教程视频

2026年09月02日

22阅读