从Python脚本中更改Python执行版本

时间:2017-02-01 11:46:36

标签: python python-3.x

是否可以在脚本中更改Python的执行版本?

我有Python 2.6.6默认加载。我想将此版本更改为3.6.0,它安装在脚本内的自定义位置(不是/ usr / bin)。因此,在脚本中,我将检查带有sys.version的Python版本,将在脚本中加载Python 3.6.0模块。它没有反映在运行环境中。这是代码:

import sys, os
pyVersion = int(sys.version.split(" ")[0].replace(".", ""))
exec(open(os.environ['MODULESHOME']+"/init/python.py").read())
if pyVersion < 360:
    print("Python 3.6.0 version required")
    print("Loading utils/python module")
    module(['load', 'utils/python/3.6.0'])
    module('li')

按预期列出模块。输出:

Python 3.6.0 version required
Loading utils/python module
Currently Loaded Modulefiles:
1) licenses                    2) cliosoft/6.32.p3(default)   3)utils/python/3.6.0

现在,当我在下一行检查python版本时,它仍然是python 2.6.6

print(sys.version)

输出:

2.6.6 (r266:84292, Jul 23 2015, 15:22:56) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)]

现在,如何在加载模块后让Python使用3.6.0代码行?

  

注意:我可以在加载脚本之前更改版本。但是,它将由多个用户使用,我没有root访问权限。所以,不可能为每一个更改版本。我只对这种方式感兴趣。

3 个答案:

答案 0 :(得分:1)

在您的最新评论中,您提到了“HERE DOC”的用法。在Python中,这些被称为'docstrings',并被写成三个引号(“”“)。关于你的问题,它们可以如下使用:

#!/usr/bin/env python

# Python 2
import os
import sys
print "1. Python version: ", sys.version
print "2. Process id: ", os.getpid()

os.execlp("python3", "python3", "-c", """

# Python 3
import os
import sys
print("3. Python version: ", sys.version)
print("4. Process id: ", os.getpid())
""")

print "5. Does not execute"

在我的机器上(Ubuntu 16.04),输出为:

1. Python version:  2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609]
2. Process id:  3085
3. Python version:  3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]
4. Process id:  3085

(您的机器上的版本可能会有所不同。)

注意两件事:

  • 版本号从2. *变为3. *
  • 流程ID保持不变3085
  • exec之后的行没有运行。实际上,exec命令“卸载”Python 2解释器。它不再需要执行文件的其余部分。

根据某些定义,这可以被视为“将Python 2. *更改为3. *”。可以使用相同的方法将2.6.6更改为3.6.0。

最后,请注意。除非您的需求是可怕的,否则我建议使用上述技术反对。以下限制可能适用:

  • 不同平台之间exec的行为差异很大。
  • 最大arg大小(Python 3字符串的大小)被硬编码到内核中。它可以小到几千字节。
  • 最后,我发现将大部分脚本置于文档字符串中令人作呕。

答案 1 :(得分:1)

扩展Ryan建议的解决方案。您可以通过类似

的操作来避免让整个脚本为字符串
import sys, os

if sys.version[0] == '2':
    with open(__file__, 'r') as f:
        _script_text = ''.join(f.readlines())
        os.execlp('python3', 'python3', '-c', _script_text)
        exit()

# Rest of your code
# | | | | | | | | |

当然,完全避免这种情况会更好,但是我认为这样做看起来不那么令人敬畏。

答案 2 :(得分:0)

env和python脚本:控制python版本 在类似Unix的系统上,python脚本通常以这一行开头:

#!/usr/bin/env python

如何在不同版本的Python下手动测试此脚本?

此“ env-shebang”习惯用法在脚本执行时有效地选择了安装在用户系统上的主要Python解释器。在任何给定的系统上,这将解析为特定版本的Python。例如,在股票Debian Lenny GNU / Linux上,它是Python 2.5。默认路径中的第一个python是/usr/bin/python,它是指向/usr/bin/python2.5的符号链接。

现在,如果您正在开发一个应该在几种不同的Python版本上运行的Python脚本,并希望在每个版本下对其进行测试,那么“ env-shebang”这个习惯用法可能会给您带来麻烦。临时编辑文件以将参数更改为env可能会成功。但这容易出错,并且很难实现自动化。

所以这是一个更好的解决方案。

假设您要在Pythons 2.5、2.6和2.7版本下进行测试,并且已经为每个版本安装了解释器。例如,在我当前的开发机器上,python 2.7位于$HOME/opt/python2.7/bin/python2.7,python 2.6位于/usr/bin/python2.6,而python 2.5位于/usr/bin/python2.5

您可以做的是在某个方便的位置为每个版本创建一个子目录。我将它们命名为“ env_pythonX.Y”,然后将它们放在$HOME/bin下(其中X和Y是主要和次要版本号)。然后,在每个目录中,建立一个指向相应版本的名为“ python”的符号链接。

再次以我的开发机为例,$HOME/bin/env_python2.7/python是指向$ HOME / opt / python2.7 / bin / python2.7的符号链接,$HOME/bin/env_python2.6/python是指向/ usr /的符号链接bin / python2.6,而$HOME/bin/env_python2.5/python是/usr/bin/python2.5的符号链接。

现在您已经准备好了。要使用(例如)python版本2.6从Unix命令行运行脚本program.py,只需定义PATH,以便首先使用$ HOME / bin / env_python2.6 / python。在提示符下,您可以输入以下内容:

PATH=$HOME/bin/env_python2.6:$PATH ./program.py

在这里,我使用了大多数现代Shell提供的语法来执行每个命令的变量分配。在命令前加上FOO = BAR表示“在变量FOO的值为BAR的环境中运行命令”。这使我们可以方便地设置搜索路径以生成我们的python,仅需一次调用即可。

这很容易与其他人重复。要按顺序手动运行每个Python版本的脚本,请使用以下一系列命令:

PATH=$HOME/bin/env_python2.7:$PATH ./program.py
PATH=$HOME/bin/env_python2.6:$PATH ./program.py
PATH=$HOME/bin/env_python2.5:$PATH ./program.py

当然,这在您的测试脚本中都是高度自动化的。

顺便说一句,如果符号链接错误,则可能会默默使用其他python版本。您可以使用python -V快速进行验证:

PATH=$HOME/bin/env_python2.6:$PATH python -V

这应该发出类似Python 2.6.5的内容。

您都准备好了。现在开始测试!