我应该放#!(shebang)在Python脚本中,它应该采用什么形式?


827

我应该把shebang放到我的Python脚本中吗?以什么形式?

#!/usr/bin/env python 

要么

#!/usr/local/bin/python

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

注:龙卷风项目采用的家当。另一方面, Django项目没有。


70
第二台不是便携式的,即使不是大多数,也会在许多计算机上失败。
Dietrich Epp

4
#!/usr/bin/python与第一个选项相比如何?我在很多示例代码中都看到了这一点。编辑:也许这就是答案.. stackoverflow.com/a/2429517/1156245
geotheory 2014年


1
我说总是用它,为什么呢?“ Zen Of Python”-第2行-“显式比隐式更好。” python.org/dev/peps/pep-0020
JayRizzo

2
坦率地说,这都不是“正确的”,因为作为作者的您不知道运行脚本时Python的正确版本在哪里。添加正确的shebang 应该是安装程序的工作。
chepner

Answers:


1116

任何脚本中的shebang行都决定了脚本的执行能力,就像独立的可执行文件一样,无需python事先在终端中键入或在文件管理器中双击(正确配置时)。不必要,但通常放在那里,因此当有人看到在编辑器中打开文件时,他们会立即知道他们在看什么。但是,您使用的家当线IS重要。

Python 3脚本的正确用法是:

#!/usr/bin/env python3

默认为版本3.latest。对于Python 2.7.latest python2代替python3

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

#!/usr/bin/env python

中给出的原因是这些建议,PEP 394,是python可以指到python2python3在不同的系统。目前,它python2在大多数发行版中都涉及,但是在某些时候可能会改变。

另外,请勿使用:

#!/usr/local/bin/python

“在这种情况下,python可能安装在/ usr / bin / python或/ bin / python上,上述#!将失败。”

- “#!/ usr / bin / env python”与“#!/ usr / local / bin / python”


4
@EliasVanOotegem如果你不能肯定,Python会中找到/usr/bin,那么你怎么能肯定的是,env将中找到/usr/bin。如果将python安装在非标准位置,则可能意味着以非标准方式安装了python,因此脚本应会快速失败。相对于对python解释器的属性进行假设并希望获得最佳结果。
沙丘2014年

65
@Dunes:env始终可以找到/usr/bin/,它的工作是利用定位箱(如Python) PATH。无论python如何安装,它的路径都将添加到此变量中并env找到它(如果未安装,则说明python未安装)。这是的工作env,这就是它存在的全部原因。这是警告环境的事情(设置环境变量,包括安装路径和包含路径)。人们一直都知道,只有在同一位置找到该命令,该命令才能起作用。这只是给定的
Elias Van Ootegem 2014年

3
@JFSebastian:是的,不能保证,也不是由POSIX标准强制执行。我以为是因为后来的IEEE版本之一确实包含一些环境内容。无论哪种方式:不,/usr/bin/env除了广泛(普遍使用)的规则外,没有任何标准的保证...
Elias Van Ootegem 2015年

6
如果使用virtualenv,即使存在,也#!/ usr / local / bin / python错误。
nullas

6
一个问题是:根据PEP394一个应该只使用python时,脚本与Python 2和Python 3。否则兼容可执行文件,它应该指向从适当的选择python2python3
amiller27

67

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

无论哪种方式,运行该程序的最终结果都不会受到影响。这只是手段的选择。


3
就是这样-没关系,因为没有“正确”的一面。这是一个完全主观的决定。
琥珀


2
没有“ python”命令,如何直接执行python文件?
2014年

5
@Zen假设您在脚本中包含了shebang(#!/ usr / bin / env python),则只需使脚本可执行即可。诸如此类的东西chmod a+x [your-script].py应该使其可执行,然后您可以./[your-script.py]在shell中调用。
skålfyfan

9
正如GlassGhost回答指出的,一个具体的优势包括它除了味道:它昭示文件的未来读者,他们正在阅读的可执行脚本,而不是意味着是导入的文件。与具有公共/私人访问控制修饰语的语言类似,shebang可用作文档及其实际效果,在某些情况下,文档方面实际上最重要。
Mark Amery 2014年

32

我应该把shebang放到我的Python脚本中吗?

将shebang放入Python脚本中以指示:

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

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

如果您手动编写shebang ,请始终使用,#!/usr/bin/env python除非有特殊原因不使用它。即使在Windows(Python启动器)上也可以理解这种形式。

注意:已安装的脚本应使用特定的python可执行文件,例如/usr/bin/python/home/me/.virtualenvs/project/bin/python。如果您在Shell中激活virtualenv,如果某些工具损坏了,那就很糟糕。幸运的是,在大多数情况下,正确的shebang是由setuptools您或您的分发包工具自动创建的(在Windows上,setuptools可以.exe自动生成包装器脚本)。

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

要选择是否应该使用pythonpython2python3在家当,见PEP 394 -在类Unix系统中的“蟒蛇”命令

  • ... python应该仅在shebang行中用于与Python 2和3源兼容的脚本。

  • 为了最终更改Python的默认版本,应仅将Python 2脚本更新为与Python 3源兼容,或者python2在shebang行中使用。


3
甚至提到PEP的第一个答案都没有足够的赞成票。??#!/usr/bin/env python本身是否有PEP ?
宾基

请不要使用#!/usr/bin/env python。请不要建议“始终使用” #!/usr/bin/env python。在99%的情况下,这是错误的做法(答案中包含的原因)。
杰伊·沙利文

1
@JaySullivan您了解源检出和已安装脚本之间的区别吗?我支持这个建议。它运作良好。
jfs

1
@jfs:重新阅读我的评论后,我发现我完全无法理解我的观点。我的意思是,大多数人都想使用“ python2”或“ python3”,而不是“ python”。无论是通过完全解决还是通过环境解决(从技术上讲都是OP的问题),您都已经回答了,我对此并不反对。
杰伊·沙利文

@JaySullivan我同意。您是否从答案中读到了从鼓舞人心的话语。它说同样的话。
jfs

15

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

#!/usr/bin/python2.7

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

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

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


是不是空间会导致它失败?
RandomInsano 2014年

1
@RandomInsano,我不这么认为。空间似乎相当普遍,并且有很多证据表明这种用法已被人们接受。但是我认为无空间可能是更规范的用法。
克里斯·约翰逊

1
你绝对是对的。刚刚在bash和tcsh上进行了测试。
RandomInsano

的结果which将为您提供一个有效的字符串,期限。您无需担心任何胆量就能使用它。
SDsolar '17

10

如果脚本旨在可执行,则应添加shebang。您还应该使用可将shebang修改为正确的安装软件来安装脚本,以使其可以在目标平台上运行。例如distutils和Distribute。


1
您不必修改#!行之后。这就是/ usr / bin / env的用途。对特定的Python解释器进行硬编码可能弊大于利。关于安装另一个Python版本或在发行版的Python与自定义Python安装之间进行切换非常脆弱。
vog 2015年

在Ubuntu中,使用的结果which将自动选择系统命令等正在使用的默认值。它是通用的,系统会将其引导至正确的安装。
SDsolar

9

shebang的目的是让脚本在您要从外壳执行脚本时识别解释器类型。通常,并非总是如此,您可以通过从外部提供解释器来执行脚本。用法示例:python-x.x script.py

即使您没有shebang声明符,这也将起作用。

为什么第一个更“便携”的原因是因为它/usr/bin/env包含了PATH声明,该声明说明了系统可执行文件所在的所有目标。

注意:Tornado严格不使用shebang,而Django严格不使用。它随您执行应用程序主要功能的方式而异。

还:它与Python并没有变化。


8

有时,如果答案不是很清楚(我的意思是,你不能,如果是或否决定),那么它没有太大的关系,直到答案,你可以忽略的问题清楚的。

#!唯一目的是为了启动脚本。Django会自行加载并使用源。不需要决定使用哪种解释器。这样,#!这里实际上没有任何意义。

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

使用的一个好理由#!是当您同时使用Python 2和Python 3脚本时-它们必须由不同版本的Python解释。这样,您必须记住python手动启动脚本时必须使用的内容(无#!内部内容)。如果混合使用这些脚本,则最好使用#!内部脚本,使其成为可执行文件,然后将其作为可执行文件启动(chmod ...)。

使用MS-Windows时,#!直到最近才有意义。Python 3.3引入了Windows Python启动器(py.exe和pyw.exe),该启动器读取#!行,检测已安装的Python版本并使用正确或明确需要的Python版本。由于扩展可以与程序相关联,因此在Windows中可以获得与基于Unix的系统中的execute标志类似的行为。


3

当我最近在Windows 7上安装Python 3.6.1时,它还安装了Windows的Python启动器,该应用程序应该可以处理shebang行。但是,我发现Python Launcher并没有做到这一点:shebang行被忽略,并且始终使用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 shebang行处理如上所述。


2

如果您安装了不同的模块,并且需要使用特定的python安装,那么shebang似乎一开始受到限制。但是,您可以执行以下操作,使shebang首先作为shell脚本被调用,然后选择python。这是非常灵活的imo:

#!/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/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    echo Using preferred python $PREFERRED_PYTHON
    exec $PREFERRED_PYTHON "$0" "$@"
elif [ -x $ALTERNATIVE_PYTHON ]; then
    echo Using alternative python $ALTERNATIVE_PYTHON
    exec $ALTERNATIVE_PYTHON "$0" "$@"
else
    echo Using fallback python $FALLBACK_PYTHON
    exec python3 "$0" "$@"
fi
exit 127
'''

__doc__ = """What this file does"""
print(__doc__)
import platform
print(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/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
    CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
    CHOSEN_PYTHON=$FALLBACK_PYTHON
fi

1
虽然我不确定这样的多语言程序通常是好的做法,但它肯定是非常有趣的方法,并且可能是这里最灵活的答案。
Ryan Amos

1
很酷。我没有意识到您可以做到这一点
user2233949

1

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

步骤如下:

首先,验证要使用的适当的shebang字符串:

which python

从中获取输出,并在第一行中将其添加(带有shebang#!)。

在我的系统上,它的响应如下:

$which python
/usr/bin/python

因此,您的shebang将如下所示:

#!/usr/bin/python

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

python filename.py

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

cp filename.py filename

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

chmod +x filename

要测试它,请使用:

./filename

最佳实践是将其移动到$ PATH中的某个位置,因此只需键入文件名即可。

sudo cp filename /usr/sbin

这样,它将可以在任何地方使用(文件名前没有./)


我怀疑这是最佳做法,因此我强烈建议您使用GlassGhost的解决方案
colidyre

我发现这很有帮助,并且对我来说效果很好。这是很好的解释。不过,我希望能提出一些评论,说明为什么这不是最佳做法。我渴望学习。
Charles Carriere

0

绝对路径与逻辑路径:

关于可移植性,这实际上是一个关于Python解释器的路径是绝对路径还是Logical/usr/bin/env)的问题。

遇到这个和谈论这个问题在一般的方式,而不支持其他证明堆栈网站其他的答案,我已经进行了一些真的,真的在上过这个问题,颗粒测试和分析unix.stackexchange.com。与其在此处粘贴答案,不如将那些对比较分析感兴趣的人指向该答案:

https://unix.stackexchange.com/a/566019/334294

作为一名Linux工程师,我的目标始终是为我的开发人员客户端提供最合适的,优化的主机,因此,我确实需要一个可靠的解决方案来解决Python环境问题。测试后,我的观点是,在(2)选项中,she-bang 中的逻辑路径更好。


-3

首先使用

which python

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

此输出可以是任何这样的

/usr/bin/python

要么

/bin/python

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

概括地说,我们可以使用:

#!/usr/bin/env

要么

#!/bin/env

3
这很可能不会移植到其他系统。#!/usr/bin/env为您做出正确的选择。
fragmentedreality

这就是使用which命令的原因-它会为您的特定系统返回正确的字符串。
SDsolar

1
...然后每次脚本将被另一台机器上运行,运行which python一改再改剧本,如果从目前的家当输出不同
fragmentedreality

2
-1这是最脆弱的解决方案。仅保证对于编写python脚本的系统正确。使用#!/ usr / bin / env python3进行可移植性
Myles Hollowed
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.