#!/usr/bin/python和#!/usr/bin/env python,哪个更好用?

10

Python脚本的shebang应该怎么写?

一些人支持#!/usr/bin/env python,因为它可以智能地找到Python解释器。另一些人支持#!/usr/bin/python,因为现在在大多数GNU/Linux发行版中,python是默认程序。

这两种变体的好处是什么?

4个回答

8

Debian Python Policy规定:

Python解释器的首选规范是/usr/bin/python/usr/bin/pythonX.Y。这确保了使用Debian安装的python并满足所有附加python模块的依赖关系。

维护人员不应使用/usr/bin/env python/usr/bin/env pythonX.Y覆盖Debian Python解释器。这样做并不明智,因为它会绕过Debian的依赖检查,并使软件包容易受到本地安装的python不完整的影响。

请注意,Debian / Ubuntu使用备选系统来管理实际指向/usr/bin/python的版本。对于我来说,至少在许多python版本中工作得非常好(我现在已经使用2.3到2.7的版本),在更新时具有出色的转换。

请注意,我从未使用过pip 我希望进行自动安全升级,因此通过aptitude安装我所有的python需求。使用官方的Debian/Ubuntu软件包比我自己搞python安装使系统更加清洁


让我强调一件事情。上述建议是针对系统安装python应用程序的。使用系统管理的python版本是完美的选择。如果您实际上在自己定制的python安装中进行操作,这与操作系统无关,那么使用env变体可能是正确的方法,以便“使用用户首选的python”,而不是硬编码任何用户自定义路径或系统python安装(它将是/usr/bin/python)。

如果您从例如Python虚拟环境中调用程序,则使用env python会导致程序行为不同。

这可能是需要的(例如,您正在编写一个仅在虚拟环境中工作的脚本)。它也可能有问题(您为自己编写了一个工具,并期望即使在虚拟环境中也能正常工作-但会因缺少软件包而突然失败)。


1
但是当你想要一个不在存储库中的软件包时会发生什么呢?那么你就需要使用 pipeasy_install,或者你需要自己安装 python setup.py - mgilson
我从未有过那种需求。根据我的经验,任何好的东西都已经被打包了 - 如果没有被打包,那么它可能在某种程度上是有问题的。此外,我们谈论的是Python,而不是Python扩展模块。你可以使用Python系统安装并添加自定义模块,而无需自己进行完整的解释器安装。 - Has QUIT--Anony-Mousse
1
我不确定你的意思。每个人的Python都有所不同,因为使Python变得非常有用的其中一个因素是您可以使用各种扩展。不需要numpy?没问题。如果需要它,则需要以某种方式获取它。需要 spacepy?我认为它并不在任何存储库中,但我使用它(据我所知它没有损坏)。我知道您可以将扩展添加到系统Python中。您也可以选择尽可能保持其原始状态,并设置自己的版本以在用户空间中工作。 /usr/bin/env 允许用户决定。 - mgilson
所有好的Python扩展都可以作为包提供,并且您可以在不重新安装Python的情况下安装扩展,即不会失去自动安全更新并因“env”更改而获得不可预测的行为。 - Has QUIT--Anony-Mousse
2
我想说的是,并非所有好的Python扩展都可用作软件包(例如 spacepy)。而且,并非所有用户都有权限在系统范围内安装扩展,最后,并非所有用户都在使用Ubuntu/Debian(/usr/bin/python 在OS-X上失败)。 如果您使用 /usr/bin/env,则用户仍然可以选择使用系统范围内的Python-他们只需要适当地管理自己的环境(无论如何他们都应该这样做)。 但再次强调- 如我在回答中所述,这真的并不重要。 您始终可以尝试使用任何安装了Python的脚本。 - mgilson

6

我认为你应该使用env变量。它是POSIX组件,因此几乎在每个系统中都可以找到,而直接指定/usr/bin/python会在许多情况下出错,例如virtualenv设置。


这实际上是期望的结果。你的虚拟环境设置可能缺少一些包;不能安全地假设 env python 将产生预期的 Python 安装。因此,如果一个共享的 Python 程序在不同的虚拟环境中运行,它将突然失败,而不是最初预期的那样...为了使用虚拟环境,我建议始终以 python script.py 的方式运行你的脚本(但对于只能在你的虚拟环境中工作的脚本,env python 方法可能更好;但仍然会使可移植性成为问题)。 - Has QUIT--Anony-Mousse
由谁期望?在这里使用 env 意味着您将使用当前由 python something.py 解析的 Python。这正是我想要的。如果我想使用不同的解释器,我会切换环境。这不是我希望脚本作者为我做出的决定。对于您发行版的软件包维护者来说,情况完全不同,他们应该强制执行系统解释器。 - filmor

4
我使用#!/usr/bin/env python作为默认安装位置,因为在OS-X上不是/usr/bin。这也适用于喜欢自定义环境的用户 -- /usr/local/bin是另一个常见的你可能会找到python发行版的地方。
话虽如此,这并不太重要。你始终可以使用任何你想要的python版本来测试脚本:/usr/bin/strange/path/python myscript.py。此外,当你通过setuptools安装脚本时,shebang似乎会被安装该脚本的sys.executable所替换 -- 我不知道pip,但我认为它表现类似。

1

正如您所指出的,它们可能都在Linux上工作。但是,如果有人为自己安装了更新版本的Python,或者某些要求使人们将特定版本保留在/usr/bin中,那么env允许调用者设置他们的环境,以便通过env调用不同的版本。

想象一下有人试图查看Python 3是否与脚本配合使用。他们将首先在其路径中添加python3解释器,但希望保持系统默认运行2.x。使用硬编码路径是不可能的。


但是使用“env”方法,系统Python程序将突然使用他在路径中某处拥有的自编译Python3运行,并且可能缺少扩展。随机的问题将突然开始出现失败。 - Has QUIT--Anony-Mousse
那就是重点,要在其他人遇到问题之前找出问题并解决,而不改变可能需要运行的文件。 - Paul Rubel
为了测试,使用显式的 test-python-installation/bin/python app.py - Has QUIT--Anony-Mousse
希望它不会直接或间接调用任何使用硬编码路径的其他Python程序。 - Paul Rubel
哦,确实可能需要这样做。仅因为它调用了另一个用Python实现的应用程序,并不意味着您希望它使用您当前正在搞乱的实验性Python解释器。通常情况下,您希望系统程序像其他用户一样按预期运行,使用相同的解释器。最坏的情况是,它们突然停止工作,因为您混乱的安装不包含它们所需的所有软件包。 - Has QUIT--Anony-Mousse

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