在不同虚拟环境中运行子进程与Python

46 投票
3 回答
50875 浏览
提问于 2025-04-17 05:53

假设我在两个不同的虚拟环境中安装了我的应用程序,分别是 myapp v1.0 和 myapp v2.0。

现在我想比较这两个版本。这个比较是用 Python 编写的。我该怎么做比较比较好呢?假设我可以分别运行它们,并且它们都能写出一个输出文件,方便我之后进行比较。

一种方法是写一个 bash 脚本(我现在就是这么做的)。我先激活一个虚拟环境,运行 myapp v1.0,然后激活另一个虚拟环境,运行 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

这样我的脚本就可以在这个环境中运行。

3 个回答

12

一个简单的方法是使用subprocess来运行一系列命令,具体做法如下(注意,shell=True是有风险的,只有在你能控制输入的情况下才应该使用)。

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

根据需要重复这个过程。

15

我觉得virtualenv的文档解释得很好。

简而言之

直接运行python的venv二进制文件并不等同于激活venv。你还需要相应地更改PATHVIRTUAL_ENV这两个变量(可以查看os.environ)。

来源

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

这条命令会改变你的$PATH,让它的第一个条目指向虚拟环境的bin/目录。(你必须使用source,因为它会直接在你的命令行环境中进行更改。)这就是它的全部功能;纯粹是为了方便。

如果你直接从虚拟环境的bin/目录运行一个脚本或python解释器(比如/path/to/ENV/bin/pip或/path/to/ENV/bin/python-script.py),那么sys.path会自动设置为使用与虚拟环境相关的Python库。但是,与激活脚本不同,环境变量PATH和VIRTUAL_ENV不会被修改。这意味着,如果你的Python脚本使用例如subprocess来运行另一个Python脚本(比如通过!/usr/bin/env python这行代码),那么第二个脚本可能不会使用与第一个脚本相同的Python二进制文件,也可能没有相同的库可用。为了避免这种情况,你的第一个脚本需要在执行第二个脚本之前,像激活脚本那样修改环境变量。

74

如果你是通过调用python可执行文件来启动你的应用程序,就像你示例中的那样,其实这非常简单:你只需要明确指向虚拟环境中的可执行文件。

import subprocess

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

这样就会在各自的虚拟环境中启动进程。

重要提示

针对评论中提到的担忧:

如果你想要运行一个子进程,并且确保使用的是当前进程正在运行的相同解释器,你需要使用sys.executable。另外,还有sys.exec_prefix可以用来访问特定于站点的目录前缀,那里安装了与平台相关的Python文件。

如果你想更深入地讨论这个话题,可以看看这个拉取请求

撰写回答