【问题标题】:Should I put #! (shebang) in Python scripts, and what form should it take?我应该把#! (shebang) 在 Python 脚本中,它应该采用什么形式?
【发布时间】:2021-08-13 13:06:13
【问题描述】:

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

#!/usr/bin/env python 

#!/usr/local/bin/python

这些是否同样便携?哪种形式用得最多?

注意:tornado 项目使用 shebang。另一方面,Django 项目没有。

【问题讨论】:

  • 第二个不便携,在许多计算机上失败,如果不是大多数的话。
  • #!/usr/bin/python 与第一个选项相比如何?我在很多示例代码中都看到了这一点。编辑:也许这就是答案.. *.com/a/2429517/1156245
  • 坦率地说,两者都不是“正确的”,因为作为作者的您不知道脚本运行时 Python 的正确版本在哪里。添加正确的shebang应该是安装程序的工作。
  • @JayRizzo:固定/可配置和隐式/显式之间存在差异。 /usr/bin/env python 显式的,表示“使用环境的默认python”,允许pip/user/OS/local admin/virtualenv通过$PATH选择一个,而/usr/bin/python 强制操作系统选择的python

标签: python shell python-3.x shebang


【解决方案1】:

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

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

【讨论】:

  • 就是这样 - 你站在哪一边并不重要,因为没有“正确”的一面。这是一个完全主观的决定。
  • 只不过是任何其他琐碎的决定。 en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality
  • 如何在没有'python'命令的情况下直接执行python文件?
  • @Zen 假设您在脚本中包含了 shebang (#!/usr/bin/env python),您只需使脚本可执行。 chmod a+x [your-script].py 之类的东西应该使它可执行,然后你可以在 shell 中调用 ./[your-script.py]
  • 正如 GlassGhost 的回答所指出的那样,除了品味之外,包含它还有一个具体的优势:它让未来的文件读者清楚他们正在阅读可执行脚本,而不是要导入的文件。与具有它们的语言中的公共/私有访问控制修饰符类似,shebang 可用作 文档 以及它们的实际效果,在某些情况下,文档方面实际上最重要。
【解决方案2】:

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

即使您没有 shebang 声明符,这也可以工作。

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

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

另外:它不会因 Python 而异。

【讨论】:

    【解决方案3】:

    如果脚本是可执行的,您应该添加一个 shebang。您还应该使用将 shebang 修改为正确的安装软件来安装脚本,以便它可以在目标平台上运行。这方面的例子是 distutils 和 Distribute。

    【讨论】:

    • 您不必修改 #!后线。这就是 /usr/bin/env 的用途。针对特定 Python 解释器的硬编码可能弊大于利。安装另一个 Python 版本或在我们发行版的 Python 与自定义 Python 安装之间切换非常脆弱。
    • 在 Ubuntu 中,使用 which 的结果将自动选择系统命令等使用的默认值。它是通用的,系统会引导它正确安装。
    【解决方案4】:

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

    #! 的唯一用途是启动脚本。 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 的系统中的执行标志类似的行为。

    【讨论】:

      【解决方案5】:

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

      #!/usr/bin/python2.7
      

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

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

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

      【讨论】:

      • 空间不会导致它失败吗?
      • @RandomInsano,我不这么认为。空格似乎很常见,并且有很多证据表明它是一种公认​​的用法。但是我认为没有空格可能是更规范的用法。
      • 你绝对是对的。刚刚在 bash 和 tcsh 上测试过。
      • which 的结果将为您提供一个有效的字符串,句号。您无需担心任何胆量即可使用它。
      【解决方案6】:

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

      正确使用(默认为版本 3.latest)Python 3 脚本是:

      #!/usr/bin/env python3
      

      正确使用(默认为版本 2.latest)Python 2 脚本是:

      #!/usr/bin/env python2
      

      以下不应使用(除非您编写的代码同时与 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" vs "#!/usr/local/bin/python"

      【讨论】:

      • @Dunes: env总是/usr/bin/ 中找到,它的工作是使用 @ 定位垃圾箱(如 python) 987654337@。不管怎么安装python,它的路径都会添加到这个变量中,env会找到它(如果没有,python没有安装)。这就是env 的工作,这就是它存在的全部原因。它是提醒环境的东西(设置环境变量,包括安装路径和包含路径)。人们一直都明白,这个命令只有在总是在同一个地方找到时才能起作用。这只是给定的
      • #!/usr/bin/env python3 在 window10 中不起作用。 #!/usr/bin/env python 适用于 Windows10 和 ubuntu
      • @DanielPinyol 如果我同时拥有 Python 2 和 3 怎么办?如何强制它在 Windows 10 上使用 Python3?
      • Debian Bullseye 默认没有python。建议显式使用python2python3。有包python-is-python2python-is-python3 再次添加了python 命令。 Python 2 自 2020 年 1 月 1 日起就无人维护,因此必须迁移到 Python 3。 wiki.debian.org/Python
      • @DanielPinyol,根据官方文档,#!/usr/bin/env python3 在通过 py.exe 使用时应该可以工作。 docs.python.org/3/using/windows.html#shebang-linesdocs.microsoft.com/en-us/windows/python/faqs#what-is-py-exe-
      【解决方案7】:

      我应该将 shebang 放在我的 Python 脚本中吗?

      在 Python 脚本中加入 shebang 来表示:

      • 此模块可以作为脚本运行
      • 是只能在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(注意:您不应手动编写后一类的路径)。

      要选择是否应该在 shebang 中使用 pythonpython2python3,请参阅 PEP 394 - The "python" Command on Unix-Like Systems

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

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

      【讨论】:

      • 第一个甚至提到 PEP 的答案都没有足够的支持。嗯? #!/usr/bin/env python 本身是否有 PEP?
      • 请不要使用#!/usr/bin/env python。请不要建议“始终使用”#!/usr/bin/env python。在 99% 的情况下,这是错误的做法(您在答案中包含的原因)。
      • @JaySullivan 你了解源代码签出和安装脚本之间的区别吗?我支持这个建议。效果很好。
      • @jfs:重新阅读我的评论后,我发现我完全无法理解我的观点。我的意思是大多数人会想要使用“python2”或“python3”,而不是“python”。是否通过完整路径或环境解决,这在技术上是 OP 问题,你已经回答了,我不反对这一点。
      • @JaySullivan 我同意。您是否阅读了答案中鼓舞人心的报价。它说的是同样的事情。
      【解决方案8】:

      回答:仅当您打算将其设为命令行可执行脚本时。

      程序如下:

      首先验证要使用的正确 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's solution
      • 我发现这很有帮助,而且对我来说效果很好。这解释得很好。但是,我希望 cmets 指出为什么这不是最佳实践。我渴望学习。
      • 我发现这比 GlassGhosts 的解决方案解释得很好,除了 shebang 格式。更好的 shebang 格式是:#!/usr/bin/env python3
      • 这帮助很大,因为我尝试在 MobaXterm 上使用 Python,它不是典型的 linux/unix 设置!
      • 如果它是一个独立的脚本,这个答案就是重点。如果文件只是一个更大程序的入口点,我肯定更喜欢创建一个符号链接来复制。
      【解决方案9】:

      当我最近在 Windows 7 上安装 Python 3.6.1 时,它还安装了适用于 Windows 的 Python Launcher,它应该可以处理 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 行处理工作如上文所述。

      【讨论】:

      • 从描述来看,问题似乎不在于 Python Launcher 忽略了 shebang。问题是 Python Launcher 已安装但由于系统配置未使用
      【解决方案10】:

      如果您安装了不同的模块并且需要使用特定的 python install,然后 shebang 一开始似乎受到限制。然而, 您可以执行以下技巧以允许调用 shebang 首先作为shell脚本,然后选择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/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
      

      【讨论】:

      • 虽然我不确定这样的多语种总体上是不是好的做法,但它肯定是非常有趣的方法,并且可能是这里最灵活的答案。
      【解决方案11】:

      这确实是一个关于 Python 解释器的路径在可移植性方面应该是absolute还是logical (/usr/bin/env)的问题。

      在彻底测试行为后,我的观点是 she-bang 中的逻辑路径是两个选项中更好的一个

      作为一名 Linux 工程师,我的目标始终是为我的开发者客户提供最合适、最优化的主机,因此 Python 环境问题是我真正需要一个可靠答案的问题。在这个和其他 Stack Overflow 网站上遇到其他答案,这些网站以一般方式谈论这个问题而没有支持证明,我在 Unix.SE 上就这个问题执行了一些真的granular testing & analysis。 p>

      【讨论】:

        【解决方案12】:

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

        如果您的代码已知是特定于版本的,如果您在 shebang 中指定预期版本,它将帮助其他人找出您的脚本在他们的环境中不运行的原因。

        【讨论】:

          【解决方案13】:

          对于打算从命令行执行的文件,我会推荐

          #! /usr/bin/env python3
          

          否则你不需要shebang(当然它不会有害)。

          【讨论】:

            【解决方案14】:

            如果你想让你的文件可执行,你必须在你的脚本中添加 shebang 行。

            #!/usr/bin/env python3 
            

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

            #!/usr/local/bin/python3 
            

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

            【讨论】:

            • 这个答案增加了哪些新信息?
            最近更新 更多