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

时间:2011-11-08 15:33:40

标签: 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

相反,我只想做:

python my_comparison_script.py

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

4 个答案:

答案 0 :(得分:33)

接受的答案并没有解决“激活”的问题。子流程中的虚拟现实。

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

import subprocess

subprocess.Popen(["virtualenv1/bin/python", "my_script.py"])
subprocess.Popen(["virtualenv2/bin/python", "my_other_script.py"])

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

重要

解决评论中提出的问题:

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

如果您想更深入地讨论此主题,请查看此pull request

答案 1 :(得分:1)

一个简单的选择是如下运行带有子进程的一系列命令。

import subprocess

subprocess.call('source activate my_virtualenv; python my_script.py', shell=True)

并根据需要重复。

答案 2 :(得分:1)

我认为 virtualenv 文档对此进行了很好的解释。

TL; DR

Runnig python venv二进制直接与激活venv相同。 您还必须相应地更改 PATH VIRTUAL_ENV 变量(请查看os.environ

Source

  

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

     

这将更改您的$ PATH,因此其第一项是virtualenv的   bin /目录。 (您必须使用source,因为它会更改您的shell   就地环境。)这就是它的全部;纯粹是方便。

     

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

答案 3 :(得分:-2)

究竟是什么问题?如何使用子进程执行shell命令?如果是这种情况,一些简单的伪代码可能看起来像:

import subprocess

myProcess = subprocess.Popen(   ['these', 'are', 'for', 'the', 'shell'],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE )

[outStream, errStream] = myProcess.communicate()

然后你可以用标准输出(outStream)做任何你喜欢的事情,并且如果存在errStream则做不同的事情(标准错误)。这包括将标准输出或标准错误写入文件。然后我猜你会把这些文件区分开来?

一个实际的代码示例(假设你在linux系统上有python 2.6+)可能看起来像:

import subprocess

with open('dateHelp.log', 'w') as dateLog:
    with open('dateHelp.err', 'w') as errLog:
        dateHelp = subprocess.Popen([ 'date', '-h'], stdout=dateLog, 
                                                     stderr=errLog)
        dateHelp.communicate()