在Python中,'# -*- coding: utf-8 -*-'是否也是一条注释?

89

既然在Python中我们使用#来插入注释,那么Python如何处理以下内容:

# -*- coding: utf-8 -*-

不同于之前的方式?


1
这在软件中经常发生。它们实际上会对注释进行一些基本的解析,并寻找特定的命令。我脑海中还有另一个例子是Hypermesh,但我相信还有许多其他的例子。 - Ma0
1
您可以将其视为解析器之前运行的预处理器,它会查看文件并决定如何进行解码。然后解析器本身开始运行并跳过该行,因为它是注释。一些类Unix文本编辑器也会执行相同的操作,以了解编辑器应该如何打开文件。 - tdelaney
5
@Ev.Kounis 也许最突出的例子是:https://en.wikipedia.org/wiki/Shebang_(Unix)。 - deceze
8
值得注意的是,就Python而言, -*- 部分是完全可选的,但包含它们似乎是惯例。 文档 表示 "GNU Emacs 也能识别该格式",这表明这可能是它的来源(@tdelaney 所说的文本编辑器的一个例子),但我曾经在从未接触过 Emacs 的代码中看到并使用过它。 - Tim Pederick
3
@MartijnPieters: 我明白了!如果你正在使用Python 2的IDLE,并且如果你的文件包含非ASCII字符(如果我添加了版权声明,则我的文件通常会包含非ASCII字符),那么它会提示你添加编码声明,使用Emacs的-*-样式。这就是我学到它的地方。 - Tim Pederick
显示剩余3条评论
2个回答

77

是的,这也是一个注释。如果位于文件顶部的前两行中,则该注释的内容具有特殊含义。

根据编码声明文档

如果 Python 脚本的第一行或第二行中的注释与正则表达式 coding[=:]\s*([-\w.]+) 匹配,则此注释将被处理为编码声明;该表达式的第一组指定了源代码文件的编码方式。编码声明必须单独占一行。如果是第二行,则第一行必须仅包含注释。

请注意,对于注释来说,使用哪种编解码器并不重要。Python 通常会忽略掉 # 标记后的所有内容,在所有可接受的源代码编解码器中,#、编码声明和行分隔符字符的编码方式完全相同,因为它们都是 ASCII 的超集。所以,解析器只需要读取一行,扫描注释中的特殊文本,必要时再读取一行,扫描注释,然后按照给定的编解码器配置解析器读取数据即可。

既然注释必须是文件中的第一或第二行(如果是第二行,则第一行必须也是注释),这是完全安全的,因为配置的编解码器只会对非注释行产生影响。


20
那么真正的问题是:我们为什么要使用 # -*- coding: X -*- 而不是 # coding: X - Jorge Leitao
15
@J.C.Leitão:你不需要这样做。任何与正则表达式匹配的内容都可以使用。但是,如果您在使用Emacs作为编辑器,则该评论还会告诉编辑器使用什么编解码方式。 - Martijn Pieters
3
有很多种方法。Unix系统使用的是“shebang line”(井号和叹号组成的一行代码),而Windows的“py”启动器将查看相同的信息。正如提到的那样,许多编辑器可以使用注释中的文本进行配置(不仅限于要使用的编解码器,还包括许多其他方面,参见emacs和vim文档)。可能还有其他方法。 - Martijn Pieters
3
不支持多字节编解码器,因此无法支持。根据PEP 263的规定:允许以上述方式处理前两行的任何编码,包括ASCII兼容编码和某些多字节编码(如Shift_JIS)。但不包括对所有字符使用两个或更多字节的编码,例如UTF-16。这是为了保持分词器中的编码检测算法简单。 - Martijn Pieters
@MikeWilliamson PowerShell可以处理使用UTF-16BE和UTF-16LE编写的脚本。 - JM0
显示剩余5条评论

21

请参阅Python参考手册中的编码声明

如果在Python脚本的第一行或第二行评论与正则表达式coding[=:]\s*([-\w.]+)匹配,则将此注释处理为编码声明;该表达式的第一个组指定源代码文件的编码。

(强调是我加的)

所以,是的,这是一个特殊的注释。它很特殊,因为解析器会尝试对其进行操作,而不像其他不在第一或第二行的注释一样忽略它。例如,在示例文件decl.py中有一个未注册的编码声明:

# # -*- coding: unknown-encoding -*-
print("foo")

如果您尝试运行此代码,Python将会尝试处理它,但最终会失败并抱怨:

python decl.py 
  File "decl.py", line 1
SyntaxError: encoding problem: unknown-encoding

3
如果您将unknown-encoding注册为一种编码方式,例如通过.pth文件,那么该编解码器实际上会被加载和使用。这为预解析代码处理提供了非常好的和有趣的机会。 - Martijn Pieters
确实,@MartijnPieters,我主要添加了这个代码示例,以证明Python处理声明的能力,而不是为其他任何声明做出任何其他主张。 - Dimitris Fasarakis Hilliard
1
https://github.com/dropbox/pyxl 是 @MartijnPieters 所提到的一个例子。 - Łukasz Rogalski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接