当python文件必须使用#!/ bin / env python时处理多个python版本

时间:2012-07-03 21:47:40

标签: python shebang

我有这个问题:

System A运行Ubuntu并需要Python 2.6来处理一系列不同的事情 我在Python 2.7上单独安装了System A 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

此解决方案的问题是:

On System A(已单独安装Python 2.7)
BLAH执行时,它会运行Python 2.7,因为我写的包装脚本(好吧到目前为止......) 当BLAH生成SIGH时,SIGH使用shebang在路径中查找python,然后遇到麻烦,因为它在env的{​​{1}}中寻找python它应该在路径中寻找PATH

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

提前致谢!

4 个答案:

答案 0 :(得分:11)

如果您的脚本需要某个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在评论中指出的那样,您可以在第一个参数中使用sys.executable来确保第二个脚本与第一个脚本一起传递给同一个解释器。 e.g

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

作为附注,可能有用也可能没用,您可以通过

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

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

答案 1 :(得分:3)

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

如果系统A和B的python2.7路径位于不同的地方(这似乎是你的情况),你可以随时创建一个符号链接:

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

它应该可以正常工作。

答案 2 :(得分:2)

为什么不使用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)

答案 3 :(得分:0)

愚蠢而简单

在shell中,如果需要:

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

在Python脚本中:

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

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