繁体   English   中英

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

[英]Change Python execution version from within Python script

是否可以在脚本中更改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访问权限。 所以,不可能为每一个更改版本。 而且我只对这种方式感兴趣。

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

#!/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字符串的大小)被硬编码到内核中。 它可以小到几千字节。
  • 最后,我发现将大部分脚本放在文档字符串中令人作呕。

扩展了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
# | | | | | | | | |

当然,完全避免这种情况会更好,但我认为这一点看起来有点不那么令人难以置信。

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 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的符号链接。

现在你准备好了。 要从Unix命令行运行脚本program.py,使用(比如说)python版本2.6,只需定义PATH,使$ HOME / bin / env_python2.6 / python成为第一个。 在提示符下,您可以键入以下内容:

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

在这里,我使用了大多数现代shell为每个命令变量赋值提供的语法。 使用FOO = BAR预先添加命令意味着“在变量FOO具有值BAR的环境中运行命令”。 这方便地让我们设置搜索路径来生成我们的python,仅用于那个invokation。

这很容易与其他人重复。 要按顺序手动运行每个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的东西。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM