我应该在Python脚本中放#!(sheband)吗?它应该采取什么形式?

我应该在我的Python脚本中放入sheband吗?以何种形式?

#!/usr/bin/env python

#!/usr/local/bin/python

这些同样便携吗?哪种形式使用最多?

备注:龙卷风项目使用了sheband。另一方面,Django项目没有。

783281 次浏览

这实际上只是一个品味问题。添加sheband意味着人们可以根据需要直接调用脚本(假设它被标记为可执行);省略它只意味着必须手动调用python

运行程序的最终结果不会受到任何影响;这只是手段的选择。

sheband的目的是让脚本在您想从shell执行脚本时识别解释器类型。大多数情况下(并非总是如此),您通过外部提供解释器来执行脚本。示例用法:python-x.x script.py

这将工作,即使你没有一个sheband声明器。

为什么第一个更“可移植”是因为,/usr/bin/env包含您的PATH声明,该声明占您的系统可执行文件所在的所有目的地。

注意:Tornado并没有严格使用sheBangs,Django也没有严格使用。它因您执行应用程序main函数的方式而异。

另外:它不会因Python而异。

如果脚本旨在可执行,您应该添加一个sheband。您还应该使用安装软件安装脚本,该安装软件将sheband修改为正确的内容,以便它可以在目标平台上工作。这方面的例子是distutils和分布式。

有时,如果答案不是很清楚(我的意思是你不能决定是或否),那么这并不重要,你可以忽略这个问题,直到答案清楚。

#!的唯一目的是启动脚本。Django自己加载源代码并使用它们。它从来不需要决定应该使用什么解释器。这样,#!在这里实际上没有意义。

通常,如果它是一个模块并且不能用作脚本,则无需使用#!。另一方面,模块源通常包含if __name__ == '__main__': ...,至少对功能进行了一些琐碎的测试。那么#!再次有意义。

使用#!的一个很好的理由是当你同时使用Python 2和Python 3脚本时——它们必须由不同版本的Python解释。这样,你必须记住手动启动脚本时必须使用python(内部没有#!)。如果你有这样的脚本,最好在内部使用#!,使它们可执行,并将它们作为可执行文件启动(chmod…)。

当使用MS-Windows时,#!没有意义-直到最近。Python 3.3引入了一个Windows Python Launcher(py.exe和pyw.exe),它读取#!行,检测已安装的Python版本,并使用正确或明确想要的Python版本。由于扩展可以与程序相关联,您可以在Windows中获得类似于基于Unix的系统中的执行标志的行为。

如果你有多个版本的Python,并且脚本需要在特定版本下运行,那么当脚本直接执行时,她可以确保使用正确的版本,例如:

#!/usr/bin/python2.7

请注意,脚本仍然可以通过完整的Python命令行运行,或者通过导入运行,在这种情况下,她-邦被忽略。但对于直接运行的脚本,这是使用她-邦的一个不错的理由。

#!/usr/bin/env python通常是更好的方法,但这有助于特殊情况。

通常最好建立一个Python虚拟环境,在这种情况下,泛型#!/usr/bin/env python将为虚拟环境识别正确的Python实例。

任何脚本中的sheang行都决定了脚本是否能够像独立的可执行文件一样执行,而无需事先在终端中输入python,也无需在文件管理器中双击它(配置正确时)。它不是必要的,但通常放在那里,这样当有人看到文件在编辑器中打开时,他们立即知道他们在看什么。然而,你使用哪个sheang行很重要。

正确(默认为版本3.latest)python3脚本的用法是:

#!/usr/bin/env python3

正确(默认为版本2.latest)python2脚本的用法是:

#!/usr/bin/env python2

以下不应该被使用(除了您正在编写与Python 2. x和3. x兼容的代码的极少数情况):

#!/usr/bin/env python

PEP 394中给出这些建议的原因是python可以在不同的系统上引用python2python3

另外,不要使用:

#!/usr/local/bin/python

"python可以安装在 /usr/bin/python或 /bin/python在这种情况下,上面的#!将失败。"

"#! /usr/bin/envpython"vs"#! /usr/local/bin/python"

我应该在我的Python脚本中放置sheband吗?

在Python脚本中放入sheband以指示:

  • 该模块可以作为脚本运行
  • 它是否只能在python2、python3上运行,还是Python 2/3兼容
  • 在POSIX上,如果您想直接运行脚本而不显式调用python可执行文件,这是必要的

这些同样便携吗?哪种形式使用最多?

如果您编写了sheang手动,那么除非您有特定的理由不使用它,否则请始终使用#!/usr/bin/env python。这种形式即使在Windows(Python启动器)上也可以理解。

注意:安装脚本应该使用特定的python可执行文件,例如/usr/bin/python/home/me/.virtualenvs/project/bin/python。如果您在shell中激活虚拟环境,某些工具中断,那就不好了。幸运的是,在大多数情况下,正确的sheang是由setuptools或您的分发包工具自动创建的(在Windows上,setuptools可以自动生成包装器.exe脚本)。

换句话说,如果脚本在源签出中,那么您可能会看到#!/usr/bin/env python。如果它已安装,那么sheband是指向特定python可执行文件的路径,例如#!/usr/local/bin/python(注意:您不应该手动编写后一类的路径)。

要选择是否应该使用pythonpython2python3,请参阅PEP 394-类Unix系统上的“python”命令

  • python应该只在sheang行中用于以下脚本源代码与Python 2和3兼容。

  • 为默认版本的最终更改做准备Python,仅Python 2脚本应更新为源代码与Python 3兼容,否则在sheband行中使用python2

先使用

which python

这将给出输出作为我的python解释器(二进制)存在的位置。

此输出可以是任何诸如

/usr/bin/python

/bin/python

现在,适当地选择sheband行并使用它。

为了概括,我们可以使用:

#!/usr/bin/env

#!/bin/env

答:只有当您计划使其成为命令行可执行脚本时。

以下是程序:

首先验证要使用的正确的sheband字符串:

which python

从其中获取输出并将其添加(使用sheband#!)在第一行。

在我的系统上,它是这样响应的:

$which python/usr/bin/python

因此,您的sheband将看起来像:

#!/usr/bin/python

保存后,它仍然会像以前一样运行,因为python会将第一行视为注释。

python filename.py

要使其成为命令,请复制它以删除. py扩展名。

cp filename.py filename

告诉文件系统这将是可执行的:

chmod +x filename

要测试它,请使用:

./filename

最佳做法是将其移动到$PATH中的某个位置,因此您需要键入的只是文件名本身。

sudo cp filename /usr/sbin

这样它就可以在任何地方工作(没有文件名之前的./)

当我最近在Windows 7上安装Python 3.6.1时,它也安装了Python Launcher for Windows,它应该处理sheang行。然而,我发现Python Launcher没有这样做:sheang行被忽略,并且始终使用Python 2.7.13(除非我使用py-3执行脚本)。

为了解决这个问题,我必须编辑Windows注册表项HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command。这仍然有值

"C:\Python27\python.exe" "%1" %*

从我早期的Python 2.7安装中。我将此注册表键值修改为

"C:\Windows\py.exe" "%1" %*

和Python Launcher sheband行处理工作如上所述。

如果您安装了不同的模块并且需要使用特定的python安装,然后sheband一开始似乎受到限制。然而,您可以像下面这样做技巧,以允许调用sheband首先作为外壳脚本,然后选择python。这非常灵活国际海事组织:

#!/bin/sh## Choose the python we need. Explanation:# a) '''\' translates to \ in shell, and starts a python multi-line string# b) "" strings are treated as string concat by python, shell ignores them# c) "true" command ignores its arguments# c) exit before the ending ''' so the shell reads no further# d) reset set docstrings to ignore the multiline comment code#"true" '''\'PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/pythonALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; thenecho Using preferred python $PREFERRED_PYTHONexec $PREFERRED_PYTHON "$0" "$@"elif [ -x $ALTERNATIVE_PYTHON ]; thenecho Using alternative python $ALTERNATIVE_PYTHONexec $ALTERNATIVE_PYTHON "$0" "$@"elseecho Using fallback python $FALLBACK_PYTHONexec python3 "$0" "$@"fiexit 127'''
__doc__ = """What this file does"""print(__doc__)import platformprint(platform.python_version())

或者更好的是,也许,为了促进跨多个python脚本的代码重用:

#!/bin/bash"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[@]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$@"; exit 127; '''

然后select.sh:

PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/pythonALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3FALLBACK_PYTHON=python3
if [ -x $PREFERRED_PYTHON ]; thenCHOSEN_PYTHON=$PREFERRED_PYTHONelif [ -x $ALTERNATIVE_PYTHON ]; thenCHOSEN_PYTHON=$ALTERNATIVE_PYTHONelseCHOSEN_PYTHON=$FALLBACK_PYTHONfi

这实际上是一个关于Python解释器的路径在可移植性方面应该是绝对还是逻辑/usr/bin/env)的问题。

在彻底测试行为之后,我的观点是在这两个选项中合理的路径是更好的

作为一名Linux工程师,我的目标始终是为我的开发人员客户提供最合适的、优化的主机,所以Python环境的问题是我真正需要一个可靠的答案。在这个和其他Stack Overflow网站上遇到其他答案,这些答案笼统地讨论了这个问题,但没有支持证明,我在Unix.SE.上就这个问题执行了一些真的粒度测试与分析

如果您使用像pyenv这样的虚拟环境,最好编写#!/usr/bin/env pythonpyenv设置将控制哪个版本的python以及从哪个文件位置开始运行脚本。

如果您的代码已知是特定于版本的,那么如果您在sheband中指定预期的版本,它将帮助其他人找到您的脚本在他们的环境中不起作用的原因。

对于打算从命令行执行的文件,我建议

#! /usr/bin/env python3

否则,你不需要sheband(当然它不会伤害)。

如果您想使您的文件可执行,您必须在您的脚本中添加sheang行。

#!/usr/bin/env python3

是更好的选择,因为它不依赖于特定的linux发行版,但可以在几乎所有的linux发行版上使用,因为它从环境变量中寻找python3路径,这对于不同的linux发行版是不同的。

#!/usr/local/bin/python3

将是python3的发行版特定路径,如果在该路径上找不到python3,则无法工作,并且在从一个发行版迁移到另一个Linux发行版时可能会导致开发人员的混淆和歧义。