为什么有些Python脚本以#!/usr/bin/env python开头?

我注意到一些Python脚本的开头是这样的:
#!/usr/bin/env python

替代

#!/usr/bin/python

Python脚本是唯一使用#!/usr/bin/env的脚本吗?是否有以#!/usr/bin/env bash#!/usr/bin/env perl开头的脚本?如果没有,那为什么Python脚本与其他脚本不同呢?

1为什么人们在Python脚本的第一行写"#!/usr/bin/env python"? - Raja G
3shebang 应该写成 #!,而不是 # - Dubu
3为什么使用“#!/usr/bin/env NAME”而不是“#!/path/to/NAME”作为我的shebang更好呢? - Scott - Слава Україні
3个回答

在脚本的shebang中使用env

Python脚本与其他任何语言的脚本没有区别。

无论是使用#!/usr/bin/env python还是#!/usr/bin/python,如果脚本是可执行的,并且在调用时没有指定语言,那么脚本将调用相应语言的解释器来运行脚本中的代码,而shebang就是找到解释器的"指南",在你的例子中是python

使用#!/usr/bin/env python而不是绝对路径的#!/usr/bin/python可以确保找到python(或任何其他语言的解释器),以防它在不同的Linux或类Unix发行版中的位置可能不完全相同,例如在这里here中解释。

尽管#!/usr/bin/python在默认的Ubuntu系统上可以工作,但使用#!/usr/bin/env python是一个好习惯。

关于env

env 是一个可执行文件,位于 /usr/bin,或者如 @hvd 所提到的(感谢提示!),作为一个兼容性符号链接在几乎所有 Linux 发行版中都可以在 /usr/bin 中找到。

来自维基百科


env是Unix和类Unix操作系统的一个shell命令。它用于打印环境变量列表或在修改当前环境的情况下运行其他实用程序。使用env,可以添加或删除变量,并通过为它们分配新值来更改现有变量。
关于你的问题:
在实践中,env还有另一种常见用法。它经常被shell脚本用来启动正确的解释器。在这种用法中,通常不会改变环境。

可以在这里找到更多关于env的信息,同样也可以在终端中的man env中查找。


关于shebang的额外信息;为什么#!python不起作用?
在评论中,有人问为什么我们不能简单地使用#!python作为shebang。由于解释器在$PATH中,这个想法是可以理解的。
原因是可执行文件是通过execve来执行的,我们可以在这里阅读到here。具体来说,以下几行:
一个解释器脚本是一个启用了执行权限并且第一行形式为的文本文件:
#! interpreter [optional-arg]
解释器必须是一个有效的路径名,用于可执行文件....
解释说明了execve要求提供完整(有效)的解释器路径。这是有道理的,因为脚本(无论是哪种语言)可能在启动过程中的任何时刻运行,甚至可能在设置$PATH之前运行。

7为了完整起见,因为这并不特定于Ubuntu,对于/usr/bin/env没有正式的存在要求,就像/usr/bin/python也没有要求一样。它可以合法地存在为/bin/env,例如。只是实际上,几乎每个发行版都将env作为/usr/bin/env提供,无论是直接还是通过兼容性符号链接。 - hvd
@rbialon 谢谢你纠正我的愚蠢的复制粘贴错误 :)! - Jacob Vlijm
3幸运的是,否则我们可能需要一个“环境”来处理“环境”。 :) - kos
在常规的bash脚本中,你需要以#!/bin/bash开头,这样脚本才知道要使用哪个解释器。在你的情况下,这是为了让脚本知道要使用Python解释器。这就是简单的答案。 - steaksauce
4作为一个提示,你应该总是使用 #!/usr/bin/env python2 或者 #!/usr/bin/env python3。你应该让你的 Python 脚本使用特定版本的解释器,而不是仅仅写上 'python'。 - John Scott
4为什么我们不能使用#!python - user423626
1@BharadwajRaju 请查看我的更新答案。 - Jacob Vlijm
@JacobVlijm,所以基本上,如果#!有一些常识来读取变量而不是坚持绝对性的话,所有这个问题都不会存在。 - Pacerier

Jacob的回答解释得很好。但是我想再提一点。
在Python中使用/usr/bin/env/还有一个作用。由于Python支持虚拟环境,使用/usr/bin/env python可以确保您的脚本在虚拟环境内运行(如果您在其中)。而/usr/bin/python将在虚拟环境外运行。

1Python的“虚拟环境”是什么意思? - Pacerier
1"虚拟环境"是一种创建特定应用程序的自定义Python部署方式,每个部署都有自己安装的软件包,而不会影响系统范围内的默认安装。 - Isac Casapu

除了上面给出的答案之外,使用/usr/bin/env可以让你的Python安装在非标准位置,并且只要你的PATH设置正确,脚本将在任何具有/usr/bin/env的UNIX风格系统上运行,这包括任何现代版本的Linux和OS/X。

这与/use/bin/python的符号链接有何不同? - Pacerier
1用户可能没有在/usr/bin中创建这样的符号链接的权限,开发者不应该假设有这个权限。此外,可能会同时安装多个Python发行版,并且使用/usr/bin/env可以通过修改PATH变量来选择要运行的版本。 - Isac Casapu