我有一个在虚拟环境中运行的Python 3.9脚本.主机环境使用Python 3.6和许多已安装的包设置.我需要能够运行一个shell脚本,该脚本只有在主机环境中运行时才能正常运行.

我不可能让3.9虚拟环境适用于此Shell脚本,也不可能更新Shell脚本以在Python 3.9中工作.

当我在命令行上运行脚本时,我需要调用deactivate,运行shell脚本,然后重新激活虚拟环境.

我希望能够在我的3.9 venv中运行的Python程序中执行与此相同的操作.但由于我试图运行Shell脚本而不是Python程序,因此我不能简单地直接调用Python 3.6解释器来解决问题.

我能想到两个解决方案:

  1. 创建一个临时shell脚本,该脚本停用venv并调用目标shell脚本.然后从我的Py3.9程序中运行该临时shell脚本.我假设停用仅适用于我运行shell脚本时创建的作用域.
  2. 为我想运行的每个程序创建一个别名,但首先运行停用,例如alias run_myprog = "deactivate; myprog",尽管必须为我需要运行的每个程序创建一个别名会有点乏味.

还有比上述两个更好的解决方案吗?

(这与this question有关.不同之处在于,问题是询问是否运行Python 3.6程序,而不是依赖于Python 3.6的shell脚本.)

推荐答案

简而言之,venv的激活只是添加了一些环境变量.

  • 虚拟_ENV
  • 虚拟_ENV_PROMPT

以及对少数其他环境变量的修改:

  • PS1
  • 路径

虚拟_ENV变量指向venv的根.根据您正在运行的操作系统,激活的作用是在Windows上增加${虚拟_ENV}/Scripts的值,在Linux和Mac等其他操作系统上增加${虚拟_ENV}/bin的值,成为您活动路径 dev的first元素.

删除它本质上与在不激活venv的情况下运行相同-甚至认为它仍然为父进程激活.

如何做到这一点取决于您如何调用shell脚本.但例如,如果您使用subprocess.它的大多数(如果不是全部)调用方法都允许您为流程传递新环境,并且您可以使用以下片段构建该环境:

import os

deactivated_env = os.environ.copy()
venv_root = deactivated_env.pop("虚拟_ENV")
paths = deactivated_env["路径"].split(os.pathsep)

deactivated_path = os.pathsep.join([x for x in paths if not x.startswith(venv_root)])
deactivated_env["路径"] = deactivated_path
deactivated_env.pop("虚拟_ENV_PROMPT")

# subprocess.run( ...., env=deactivated_env)

这样,您的shellScript就应该重新使用系统范围的Python及其设置了.

Python相关问答推荐

Polars比较了两个预设-有没有方法在第一次不匹配时立即失败

仿制药的类型铸造

连接两个具有不同标题的收件箱

将jit与numpy linSpace函数一起使用时出错

如何在Windows上用Python提取名称中带有逗号的文件?

删除所有列值,但判断是否存在任何二元组

如何找到满足各组口罩条件的第一行?

DataFrames与NaN的条件乘法

在两极中过滤

从Windows Python脚本在WSL上运行Linux应用程序

在方法中设置属性值时,如何处理语句不可达[Unreacable]";的问题?

合并与拼接并举

使用__json__的 pyramid 在客户端返回意外格式

从一个df列提取单词,分配给另一个列

需要帮助使用Python中的Google的People API更新联系人的多个字段'

如何使用pytest在traceback中找到特定的异常

如何将一个文件的多列导入到Python中的同一数组中?

如何在Polars中创建条件增量列?

使用pythonminidom过滤XML文件

在Django REST框架中定义的URL获得404分