【问题标题】:Dealing with multiple python versions when python files have to use #!/bin/env python当 python 文件必须使用 #!/bin/env python 时处理多个 python 版本
【发布时间】:2025-11-26 07:35:02
【问题描述】:

我有这个问题:

System A 运行 Ubuntu,需要 Python 2.6 来处理很多不同的事情。
我在System A 上单独安装了Python 2.7
System B 本身具有Python 2.7

我有一个 python 脚本BLAH,上面写着#!/bin/env python
再往下,它执行另一个脚本SIGH,上面也写着:#!/bin/env python

BLAH 需要在System ASystem B 上运行,并且它始终需要在Python 2.7 上运行

----
到目前为止,我的部分解决方案:
有一个包装脚本,首先尝试查看 which python 是否指向 Python 2.7
如果没问题,那么使用 python 的路径运行BLAH
否则尝试 which python2.7 并使用该路径运行 BLAH ,并将该路径添加到 env PATH

这个解决方案的问题是:

System A 上(单独安装了 Python 2.7)
BLAH 执行时,由于我编写了包装脚本,它使用 Python 2.7 运行(到目前为止还可以......)
BLAH 产生SIGH 时,SIGH 使用shebang 在路径中查找python 然后它遇到了麻烦,因为它在envPATH 中寻找python,它应该在寻找python2.7路径。

有没有干净的方法来处理这个问题?

提前致谢!

【问题讨论】:

  • 你能导入,然后从 BLAH 运行 SIGH 吗?
  • 我不确定您是否需要将从which 获得的路径添加到PATH -- which 实际上只会搜索包含在PATH 中的路径。

标签: python shebang


【解决方案1】:

如果你的脚本需要特定的 python 版本,例如 2.7,我会将第一行更改为

#!/bin/env python2.7

然后确保python2.7 在您的路径上(您可能需要根据需要添加符号链接)。在我使用的所有发行版中,这些符号链接已经存在。

(事实上,python 通常是指向 pythonX 的符号链接,这是指向 pythonX.Y 的符号链接,或者在我的情况下是 python -> python2 -> python2.7。)

无需对完整路径进行硬编码,因为这可能因发行版或盒子而异。

但是,由于路径上名为 python2.7 的可执行文件应该没有歧义,因此您应该没问题,不必担心硬编码路径。

或者,您可以在第一个脚本中直接调用 python 解释器,如下所示:

subprocess.Popen(['pythonX.Y', SCRIPT_NAME])

而不是

subprocess.Popen([SCRIPT_NAME])

编辑 正如 J.F. Sebastian 在 cmets 中指出的那样,您可以在第一个参数中使用 sys.executable 以确保将第二个脚本传递给与第一个脚本相同的解释器。例如

subprocess.Popen([sys.executable, SCRIPT_NAME])

附带说明,这可能有用也可能没用,您可以通过

访问脚本内部“当前”Python 解释器的版本
import sys
print(sys.hexversion)

这可能有助于确定正确的解释器是否正在运行。

【讨论】:

  • @jedwards 某些 shebang 无法正常工作,在 apache 中出现无效路径错误
【解决方案2】:

我要做的是首先将#!/bin/env直接更改为python2.7路径,例如:#!/usr/local/bin/python2.7就可以了。

如果系统 A 和 B 的 python2.7 路径位于不同的位置(这似乎是您的情况),您始终可以像这样创建符号链接:

ln -s /bin/python2.7 /usr/local/bin/python2.7

它应该可以正常工作。

【讨论】:

    【解决方案3】:

    为什么不使用 virtualenv?它允许您使用安装的任何 python 版本(除了其他东西)...

    starenka /tmp % virtualenv test -ppython2.6
    Running virtualenv with interpreter /usr/bin/python2.6
    New python executable in test/bin/python2.6
    Also creating executable in test/bin/python
    Installing setuptools............................done.
    Installing pip...............done.
    
    starenka /tmp % source test/bin/activate
    
    (test)starenka /tmp % which python
    /tmp/test/bin/python
    
    (test)starenka /tmp % python --version
    Python 2.6.8
    
    (test)starenka /tmp % echo '#!/usr/bin/env python\nimport sys; print sys.version_info' > test/test.py
    
    (test)starenka /tmp % chmod +x test/test.py
    
    (test)starenka /tmp % test/test.py
    (2, 6, 8, 'final', 0)
    
    starenka /tmp % virtualenv test7 -ppython2.7
    Running virtualenv with interpreter /usr/bin/python2.7
    New python executable in test7/bin/python2.7
    Also creating executable in test7/bin/python
    Installing setuptools............done.
    Installing pip...............done.
    starenka /tmp % source test7/bin/activate
    
    (test7)starenka /tmp % which python
    /tmp/test7/bin/python
    
    (test7)starenka /tmp % python --version
    Python 2.7.3rc2
    
    (test7)starenka /tmp % echo '#!/usr/bin/env python\nimport sys; print sys.version_info' > test7/test.py
    
    (test7)starenka /tmp % chmod +x test7/test.py
    
    (test7)starenka /tmp % test7/test.py
    sys.version_info(major=2, minor=7, micro=3, releaselevel='candidate', serial=2)
    

    【讨论】:

      【解决方案4】:

      愚蠢而简单

      如果需要,在 shell 中:

      ln -s /path/to/your/python2.X /usr/local/bin/python2
      

      在 Python 脚本中:

      #!/bin/bash
      "exec" "python2" "$0"
      

      我遇到过这类问题,这个解决方案解决了大多数情况,并且可以轻松地从一个系统移植到另一个系统(您可能会面临系统之间的不同路径、不同版本的软件......)。首先创建一个符号链接以确保您将运行正确版本的 Python(现在尤其如此,如果 Python3 只是 Python,您现在永远不会),然后依赖 bash 环境。因此,您不必在每次将系统定位为不需要麻烦的包的 util-script 时更改脚本。

      【讨论】: