为什么在Linux中使用Python需要添加#!/usr/bin/python这一行?

相当简单的问题:在Linux中,为什么Python需要这一行代码?
#!/usr/bin/python

在Python文件的开头,因为Windows不支持?

它是做什么的?因为“链接到Python”这个描述有点模糊...


30以下答案都是正确的,但没有一个解释为什么Windows不需要这行代码。Windows依赖于文件扩展名(.后面的部分)来确定文件的类型。即使Windows也在逐渐改变这一点:检查Microsoft Word文件的前几行,它会说明它实际上是一个Microsoft Word文件。 - Charles Green
@CharlesGreen 以前用于Word文档(.doc)的旧格式包含一个确认文件类型的魔术头部,就像可执行文件开头的“MZ”一样。现在Word使用的格式(.docx)基本上是一个具有不同扩展名的ZIP文件。 - Nathan Osman
即使新的docx格式中包含大约130个字节的信息表明该文档是一个Word文档,以XML格式存储。 - Charles Green
10房间里的大象是,除非你兼容Python 2和3,否则绝对不应该使用/usr/bin/python。原因是:arch将其符号链接到python3,这一举措得到了PSF的认可,他们自己也建议不要这样做。 - Yet Another User
相关链接:http://askubuntu.com/questions/590410/how-do-i-run-python-code-as-a-script - Jacob Vlijm
10以下答案中暗示了,但并未明确说明不是必需的。只有当您想要仅通过脚本名称执行脚本时才需要它。您也可以始终运行python myscript.py - Chris H
3@CharlesGreen 我们不应该知道为什么Windows不这样做,哈哈。这是SO的事情。 - Rinzwind
2@YetAnotherUser 自 Python 3 发布以来已经过去了六年零十一个月,我认为现在人们最好将默认设置为 3,并在必要时明确指定使用 2。 - JAB
同样地,由于您可以更改Windows的基于扩展名的行为,有时您仍然需要显式地使用python <script>来运行Python脚本。在我以前在Windows上开发Python时,我习惯将.py文件的默认运行程序设置为gvim - Kyle Strand
1Shebang是一个魔数;链接的维基百科条目部分提到:Unix或Linux脚本可能以"shebang"(#!23 21)开头,后面跟着解释器的路径,如果解释器与调用脚本的解释器不同的话。 - Elliott Frisch
@KyleStrand,我经常在Windows上运行python <script>,通常在Linux上运行我在Windows下编写的脚本时也是如此。这可能与我写python脚本的原因有关:对于计算机管理任务,我使用bash(Linux)或.bat + bash(带cygwin的Windows)的奇异混合,而我的Python脚本则主要用于处理数据。 - Chris H

-- coding: utf-8 -- 对我来说也是个好办法

- Rafs
8个回答

Python在Linux上没有任何特殊要求。它是Unix/Linux上的程序加载器使用所谓的"shebang"行。这实际上是一种特性而不是限制,但我们稍后会详细介绍。关于"shebang"的维基页面有更多细节,但我也会在这里概述并与Windows进行比较。

首先,让我们看看Windows上的情况:

当您尝试打开或运行一个文件时,Windows首先会检查该文件的扩展名。这是文件名的最后一部分,以.开头。对于Python文件来说,通常是.py
Windows根据文件扩展名查找要采取的操作。
这些信息记录在Windows注册表中;当安装Python时,它通常告诉Windows应使用新安装的Python应用程序(即Python解释器)打开.py文件。
几种文件类型具有内置的行为;例如,可执行文件(如Python解释器本身)必须以.exe结尾,而.bat文件则作为Windows批处理脚本执行。
特定文件类型的操作是可定制的。例如,您可以告诉Windows,不要使用python.exe运行.py文件,而是使用其他程序打开它们,比如文本编辑器notepad.exe
在这种情况下,为了运行Python脚本,您需要手动调用python <scriptname>.py(或编写一个.bat文件来代替您执行此操作)。
现在,如果Python脚本的顶部有一个shebang行(#!/usr/bin/python#!/usr/bin/env python),会发生什么呢?嗯,由于在Python中#是一行注释,Python解释器会忽略它。这就是为什么Unix/Linux世界中使用大多数脚本语言都以#开头作为注释行的原因之一。
所以说Windows "不需要" #!行有点误导人;Windows根本看不到#!行,实际上依赖于文件扩展名来告诉它该做什么。这有几个缺点:
  • 你必须将Python脚本命名为以.py结尾,以便自动识别。
  • 没有简单的方法来区分Python2脚本和Python3脚本。
  • 正如前面提到的,如果更改了.py文件类型的默认启动行为,Windows将不再自动使用Python运行这些脚本。请注意,这可能是无意中发生的。
现在,让我们来看看Unix/Linux如何启动脚本:
首先要注意的是,与Windows不同,Unix/Linux并不试图使用特定的程序来“打开”Python脚本,至少在概念上不是这样;操作系统知道脚本是可以执行的,这是因为有一个叫做“执行位”的东西(超出了本回答的范围)。所以,如果你不小心输入了#!/usr/bin/pthon而不是#!/usr/bin/python,你会收到一个包含以下文本的错误信息:
/usr/bin/pthon: bad interpreter: No such file or directory.

“解释器”这个词给了我们关于 shebang 行的角色的线索(尽管从技术上讲,指定的程序可以是除解释器之外的其他东西,例如 cat 或文本编辑器)。当您尝试执行一个文件时,会发生以下情况:

  • Unix/Linux 程序加载器查看该文件的前两个字节;如果这两个字节是“#!”,那么加载器将解释剩余的 shebang 行(不包括 shebang 本身)作为一个命令来启动一个“解释器”,并以此运行文件内容作为脚本。
  • 程序加载器启动指定的解释器,并将原始文件的路径作为参数传递给它。

这有几个优点:

  • 脚本编写者可以更好地控制使用哪个解释器(解决了 Python2/Python3 的问题),有时还可以向解释器传递额外的参数(详细信息请参阅维基页面)。
  • 脚本的文件名将被“忽略”,因此您可以随意为 Python 脚本命名。
请注意,Unix/Linux在运行Python脚本时不需要使用shebang行。请记住,shebang行的实际作用只是允许程序加载器选择一个解释器。但就像在Windows中一样,这也可以手动完成。
python <myscript>

1在Windows上,您可以轻松地为Python 2 / Python 3脚本使用.py2.py3扩展名。因此,Linux(+x位)和Windows(文件扩展名)都需要文件系统中的元数据。主要区别在于+x位在传输过程中更容易丢失。这不一定是一个缺点。 - MSalters
1@MSalters 执行位中编码的信息要少得多。请注意,在一个系统上可能有多个Python2解释器(在我以前的工作中,Ruby和其他语言也存在类似的情况);通过shebang行来处理这个问题几乎是微不足道的,而在Windows上,随着你尝试管理多个相似文件类型,情况变得更加棘手。 - Kyle Strand
此外,扩展名真的算作“元数据”吗?它只是文件名的一部分而已。 - Kyle Strand
3文件的元数据包括完整的文件名、创建时间、访问权限等。只有内容本身才是数据,而不是元数据。至于“多个解释器”,这确实是一个真正的问题,也正是为什么它不应该出现在shebang行中的原因。如果你有/usr/bin/i686/python/usr/bin/amd64/python呢?这很合理,但它会破坏那些在/usr/bin/python上有硬编码假设的Python脚本。解释器的选择不是脚本作者的选择,而是脚本用户的选择。脚本作者只能选择语言(方言)。 - MSalters
1@MSalters 嗯,这就是 /usr/bin/env 的作用,还有 env-setup 脚本。Windows 版本是什么呢?在启动 .py 文件之前运行 regedit 脚本以确保获得所需的解释器吗? - Kyle Strand
右键点击,选择“打开方式”。 - MSalters
很好的回答。应该是“[...] 如果这两个字节是 #!,那么加载器会解释整个第一行的剩余部分 [...]”吗? - Rmano
@Rmano 谢谢,说得好。我已经澄清了。 - Kyle Strand

你所指的那一行是用来告诉计算机在直接运行文件/脚本时应使用哪个程序/解释器,并传递给该程序的任何参数。然而,这并不是Python的要求,而是Linux内核/系统的要求,如果你打算直接运行脚本(而不是通过下面的语法将其传递给Python)。
如果你要执行"python script.py"或类似的命令,则不需要这行代码。只有当你打算直接运行脚本/文件而不提供要使用的解释器(如"python")时,才需要这行代码。
对于一个Bash脚本,它可能会有类似这样的内容:
#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;

这将告诉系统,在运行时应该通过/bin/bash来运行,这是系统上的一种shell / shell脚本语言之一。
对于Python代码,你需要通过Python运行可执行文件,因此你需要告诉它你想要在其中运行的解释器。
#!/usr/bin/python [optional Python arguments]
# Python code here
...
exit()

这个,就像对于Bash来说,表示应该使用/usr/bin/python(这可能是Python 2或Python 3,取决于您的个人系统配置)。
以这种方式,您可以直接运行`./filename.py`、`./executable`或`./scripttorun`。
如果没有在开头加上那一行,并且假设您已将文件/脚本设置为可执行,并且假设您正在使用Python脚本,那么如果没有`#!/usr/bin/python`这一行,您将不得不运行`python filename.py`或类似的命令。(对于Bash脚本,您将不得不运行`bash script.sh`,对于其他脚本/语言(如Perl,Ruby等),也是类似。)
上面的语法高亮在每个部分中都是特定于语言的,尽管它并不重要。

1有趣的一点是,在shebang之后,可以指定额外的参数,在大多数情况下,方式与直接调用解释器相同(例如#!/bin/bash -x#!/usr/bin/perl -lan等)。 - kos
7@kos:我认为你可以指定一个额外的参数,当使用/usr/bin/env python来获取正确的Python时,这可能会很麻烦。 - mike3996
@progo 不确定 env 的问题是什么,但问题似乎不是参数的数量:#!/usr/bin/perl -l -a -n 有三个参数,但它可以工作。虽然我还是无法理解确切的问题。 - kos
当明确调用一个解释器并将脚本作为参数时,没有理由让后者以./开头。换句话说,只需使用python filename.pybash script.sh即可正常工作。只有在命令名称中包含./时才需要,这样可以告诉shell不要在$PATH中搜索(可能找不到当前目录中的文件),而是按照您指定的路径执行。但这不适用于命令参数。 - Marc van Leeuwen
@kos:问题可能出现在env如何从内核接收其余参数的方式上。它们可能都被假设为一个大的参数,没有进行按空格分割。抱歉表达不清楚,我对此的细节记忆不太深刻了。 - mike3996
@MarcvanLeeuwen 我知道,但是我用它来表示“这个目录”。我会进行编辑。 - Thomas Ward

这一行:

#!/usr/bin/python

被称为“shebang”,它指示将用于解释文件中其余命令的解释器二进制文件的路径。它通常是脚本的第一行。
因此,行#!/usr/bin/python表示文件的内容将由位于/usr/bin/pythonpython二进制文件进行解释。
请注意,内核会解析shebang行,然后最终将脚本作为参数调用。
python script_name

同样地,在#!/bin/bash的情况下:
bash script_name

2我不认为我曾经在shebang中见过连字符。由于这个词是由"hash"和"bang"组成的,你的拼写并不清楚,因为它看起来像是**"she"**和"bang"的组合。 - Kyle Strand
你可以称之为“hashbang”(# = “hash”)或者“shebang”(# = “sharp”),取决于你如何称呼 # 字符。然而,“shebang”确实更常见。@KyleStrand - Byte Commander

从技术上讲,这并不需要。它需要一个指向脚本执行环境的路径。为了确保你的未来脚本能够在任何地方安装Python的环境中运行,最好在脚本中包含/usr/bin/env,然后指定python。这样可以保证你的脚本在Python环境中运行,而不管Python安装在哪里。
出于兼容性的考虑,你应该这样做,因为你无法确定与你共享代码的下一个人是否在usr/bin/python中安装了Python,或者他们是否有权限访问这些系统文件。
这是一个类似的问题和答案,你可以在Stack Overflow上找到:这里是一个类似的问题和答案
在你的脚本中,这看起来像是这样的:
#!/usr/bin/env python

我也看到一些关于如何指定python3的问题。以下是如何做到的:
#!/usr/bin/env python3

在Linux中,Python可能需要或不需要#!(shebang)行。这取决于如何处理Python代码,无论是在Python交互模式下运行代码还是在Python脚本中。 Python交互模式允许用户直接输入和运行Python代码,不需要shebang行。要运行交互模式,请打开终端并键入python(Python 2.X)或python3(Python 3.X)。
$  python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

$  python3
Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Python脚本允许用户将Python代码写入和保存到纯文本文件中,然后稍后运行代码。这可能需要或不需要shebang行。然而,在Linux中使用Python脚本时,有两个已知原因需要shebang行。

  1. 在可执行脚本中运行Python代码,即定义代码应如何运行以及使用什么解释器;

  2. 根据特定版本的Python运行Python代码,即仅运行与Python 2.X或Python 3.X兼容的代码

使用Python脚本进行练习

以下是我用来展示#!(shebang)行是否需要的文件列表和内容。

$  ls -ln *.py
-rw-rw-r-- 1 1000 1000  94 Dec 14 18:37 hello1.py
-rwxrwxr-x 1 1000 1000 116 Dec 14 18:37 hello2e.py
-rw-rw-r-- 1 1000 1000 116 Dec 14 18:37 hello2.py
-rwxrwxr-x 1 1000 1000 117 Dec 14 18:37 hello3e.py
-rwxrwxr-x 1 1000 1000 120 Dec 14 18:37 hello3m.py
-rw-rw-r-- 1 1000 1000 117 Dec 14 18:37 hello3.py

$  file *.py
hello1.py:  ASCII text
hello2e.py: Python script, ASCII text executable
hello2.py:  Python script, ASCII text executable
hello3e.py: Python script, ASCII text executable
hello3m.py: Python script, UTF-8 Unicode (with BOM) text executable
hello3.py:  Python script, ASCII text executable
  • hello1.py 只包含源代码。

    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
    
  • hello2.py 包含源代码和 shebang 行。

    #!/usr/bin/env python
    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
    
  • hello2e.pyhello2.py 相同,并且可执行。

  • hello3.pyhello2.py 相同,只是将第一行改为 #!/usr/bin/env python3 以适应 Python 3。

  • hello3e.pyhello3.py 相同,并且可执行。

  • hello3m.pyhello3.py 相同,并且可执行,只是在文本编辑器(如 Mousepad)中保存时选择了 "Write Unicode BOM" 选项。

超过这个点,用户将会被呈现出两种运行Python脚本的方法。以下是两种方法的演示。
方法一:使用Python程序运行
下面是在Python 2和Python 3中运行源代码时的命令和输出。
$  python hello1.py
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  python3 hello1.py
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

两个版本的Python都能成功运行脚本。因此,在使用pythonpython3命令运行Python脚本时,不需要添加shebang行。

方法二:作为Python脚本运行

以下是在带有shebang行的情况下运行源代码时的命令和输出,这适用于Python 2和Python 3,包括非可执行和可执行的情况。

$  ./hello1.py
bash: ./hello1.py: Permission denied

$  ./hello2.py
bash: ./hello2.py: Permission denied

$  ./hello3.py
bash: ./hello3.py: Permission denied

$  ./hello2e.py 
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  ./hello3e.py 
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

前三个脚本都失败了,因为这些脚本无法执行,不管是否有shebang行(支持证明,请参见下面的附加示例)。而最后两个脚本具有shebang行并且可执行。
显然,一个已经被设置为可执行的脚本在没有shebang行的情况下基本上是无用的。因此,在运行可执行脚本中的Python代码时,需要shebang行,并且脚本必须是可执行的。

当shebang行失效时

在我准备和测试的示例中,将hello3m.py作为可执行脚本运行失败并返回了一个错误。
$  ./hello3m.py 
./hello3m.py: line 1: #!/usr/bin/env: No such file or directory

这是一个已知限制,即Shebang不起作用或变得无效。当一个文件保存为Unicode BOM(字节顺序标记)时,它将无法像可执行的Python脚本一样正常运行。

附加例子

这个附加例子仅应被视为支持证据。用户应避免运行此示例,尽管结果是无害的。

我创建了另一个文件称为hello1e.py,它包含与hello1.py相同的内容并且可以执行。运行此脚本会返回语法错误。

$  ./hello1e.py 
./hello1e.py: line 2: syntax error near unexpected token `"Hello from Python %s\n"'
./hello1e.py: line 2: `sys.stdout.write("Hello from Python %s\n" % (sys.version,))'

运行此脚本时,首先,鼠标光标将变为加号形状,并且在外观上不会有任何动作。直到我在桌面或终端窗口上点击后,语法错误才会显示出来。然后,此脚本将在与脚本相同的目录中创建一个名为sys的文件。
$  file sys
sys: PostScript document text conforming DSC level 3.0, Level 1

已经确定将sys文件识别为没有文件扩展名的PostScript文件。该文件可以在文档查看器(如Evince)中打开,实际上文件中包含了我之前点击的窗口的截图。根据我的经验,该文件的大小可能达到几兆字节。

再次强调,必须添加shebang行,并且在将Python脚本作为可执行脚本运行时,脚本必须具有可执行权限。否则,脚本将会出现上述描述的问题。

附加说明

术语“使其可执行”或“必须具有可执行权限”指的是运行脚本的权限。可以通过在终端中运行chmod +x 文件名命令,或者在文件管理器的属性窗口中勾选“允许此文件作为程序运行”或类似选项来实现。

虽然其他现有答案已经涵盖了几乎所有内容,但本答案采用了不同的方法,通过使用实际示例来解释问题。代码语法已经经过精心编写,以便这些示例可以在Python 2或Python 3中运行。

Python代码已经从在Windows上使用Python在Unix平台上使用Python进行了调整,还添加了一行代码,用于编写无处不在的“Hello, World!”程序。
所有的代码和命令都经过了充分的测试,并且在Xubuntu 14.04系统中正常工作,该系统默认安装了Python 2.7和Python 3.4。

这意味着当执行该文件时,您的计算机知道要使用程序/usr/bin/python来执行它,这就是如何将其与其他语言区分开来的方式,比如bash,您可以使用#!/bin/bash。这样您就可以简单地运行:
./[file-to-execute]

而且它会知道要使用哪个文件来执行,而不是你自己需要像这样指定:
python ./[file-to-execute].py
#!部分通常被称为shebangcrunch banghashbang

2还有一个哈希符号。 - Naftuli Kay

如果您安装了几个版本的Python,/usr/bin/env将确保使用的解释器是环境中 $PATH 的第一个。另一种方法是硬编码类似于 #!/usr/bin/python 这样的内容;
在Unix中,一个可执行文件如果需要解释执行,可以在第一行的开头添加#!,后面跟着解释器和可能需要的任何标志。
这条规则仅适用于基于UNIX的系统。

对于像Linux这样仍然使用Python 2.x作为标准的操作系统非常有帮助,但大多数人也会下载3.x。

默认情况下运行2.x。因此,我的3.x代码,我会添加前缀

#!/usr/bin/env python3

为了让3.x版本能够运行这段代码。我甚至可以指定到小修订版本(Python 3.x.y.z),如果我选择使用beta版本或稍旧的版本的话。