使用python在不同的virtualenv中运行子进程

Ago*_*Ago 24 python virtualenv

假设我在2种不同的虚拟环境中安装了2个不同版本的应用程序.myapp v1.0和myapp v2.0.

现在我想比较一下.比较是用python本身编写的.最好的方法是什么?我们假设我可以单独运行它们并且都写一个输出文件,我可以稍后比较.

一种方法是编写一个bash脚本(这就是我目前所拥有的).我激活一个virtualenv,运行myapp v1.0,激活另一个virtualenv,运行myapp v2.0.稍后在这些文件上运行比较模块.但是我想在那里添加更多的动态(采用一些可选的参数等),使用python会更容易.

编辑:

目前我有类似的东西(一个bash脚本):

source virtualenv1/bin/activate
python my_script.py
deactivate

source virtualenv2/bin/activate
python my_other_script.py
deactivate

python my_comparison_script.py
Run Code Online (Sandbox Code Playgroud)

相反,我只想这样做:

python my_comparison_script.py
Run Code Online (Sandbox Code Playgroud)

我的脚本将在此内部运行.

Oli*_*ter 34

接受的答案没有解决在子流程中"激活"virtualenv的问题.

如果你通过调用python可执行文件启动你的应用程序,就像在你的例子中一样,它实际上非常简单:你只需要明确指向virtualenv中的可执行文件.

import subprocess

subprocess.Popen(["virtualenv1/bin/python", "my_script.py"])
subprocess.Popen(["virtualenv2/bin/python", "my_other_script.py"])
Run Code Online (Sandbox Code Playgroud)

将在相应的virtualenvs中启动流程.

重要

为解决评论中提出的问题:

如果要运行子进程并确保使用当前进程运行相同的解释器,则必须使用sys.executable.也可用:sys.exec_prefix用于访问特定于站点的目录前缀,其中安装了与平台相关的Python文件.

如果您想对此主题进行更深入的讨论,请查看此拉取请求.

  • 实际上,这还不够.激活virtualenv也会改变一些环境变量,调用特定的virutalenv的python不会这样做.结果,将加载错误的库. (10认同)
  • 我刚刚尝试了第二种情况,这是正确的:从my_script.py中调用子进程将再次使用系统Python进行验证.尴尬. (9认同)
  • @qarma:我不同意 - 这种方法有效,我在自己的生产代码中使用它.我[不是唯一推荐它的人](http://stackoverflow.com/a/14792407/2626627).如果你将你所指的环境变量具体化,并提供一个测试用例,表明在哪种情况下会加载错误的库,我会很有帮助. (2认同)
  • 是的我也在virtualenv的网站上看过这个建议.至少有两种情况,直接运行virtualenv链接python解释器与使用activate不同:当设置了'PYTHONHOME`并且目标程序使用`command`或`Popen`运行另一个Python程序时.后者如果说可能是模糊的. (2认同)
  • 在窗户上。在调用 python 或脚本之前,我需要“set PYTHONPATH= & workon virtualenv1”。否则,python 解释器 PYTHONPATH 仍然指向系统库。 (2认同)

小智 6

一个简单的选择是使用子进程运行一系列命令,如下所示(注意这shell=True是有风险的,只有在您可以控制输入时才应该使用)。

import subprocess
    
cmd = 'source activate my_virtualenv; python my_script.py'
subprocess.call(cmd, shell=True, executable='/bin/bash')
Run Code Online (Sandbox Code Playgroud)

并根据需要重复。

  • `Source` 在子进程内不可用,因为子进程使用 /bin/sh。这将给出错误:“/bin/sh: 1: 源: 未找到” (2认同)
  • 使用“.”代替“source”,这是可移植的等效项 (2认同)

小智 6

我认为virtualenv文档很好地解释了它。

TL; 博士

运行过程中出现蟒蛇VENV二进制直接是一样的激活VENV。您还必须相应地更改PATHVIRTUAL_ENV变量(查看os.environ

来源

$ source /path/to/ENV/bin/activate

这将更改您的 $PATH,因此它的第一个条目是 virtualenv 的 bin/ 目录。(您必须使用源代码,因为它会就地更改您的 shell 环境。)这就是它所做的全部;这纯粹是一种方便。

如果您直接从 virtualenv 的 bin/ 目录(例如 path/to/ENV/bin/pip 或 /path/to/ENV/bin/python-script.py)运行脚本或 python 解释器,则 sys.path 将自动为设置为使用与 virtualenv 关联的 Python 库。但是,与激活脚本不同的是,环境变量 PATH 和 VIRTUAL_ENV 不会被修改。这意味着,如果您的 Python 脚本使用例如 subprocess 来运行另一个 Python 脚本(例如,通过 !/usr/bin/env python shebang 行),则第二个脚本可能不会使用与第一个相同的 Python 二进制文件执行,也可能不会具有相同的库对它可用。为了避免这种情况发生,在执行第二个脚本之前,您的第一个脚本需要以与激活脚本相同的方式修改环境变量。