如何获取当前 shell 并在其中执行命令?

How to get current shell and execute command in it?

我有一个名为 'venv' 的 virtualenv,它是激活的:

(venv)>

我写了代码,我将在 virtualenv (main.py) 中 运行:

import subprocess
result = subprocess.run('python other.py', stdout=subprocess.PIPE)

但是当我 运行 main.py 文件时:

(venv)> python main.py

subprocess 不在 virtualenv 中执行命令 (python other.py) 即 venv

如何在当前 virtualenv 会话中 运行 subprocess 命令?

如果没有父进程的参与,子进程无法 运行 命令。

这就是为什么 ssh-agent 需要使用 eval "$(ssh-agent -s)" 来调用它在输出上发出的 shell 命令,例如。因此,你在这里要求的字面上的东西是不可能的。

还好,也没必要


virtualenvs 使用子进程继承的环境变量。

这意味着您实际上不需要使用激活了 virtualenv 的同一个 shell 来启动一个新的 Python 解释器来使用 interpreter/libraries/etc。来自那个 virtualenv.


subprocess.run 必须传递 list,或者必须使用 shell=True

要么这样做(哪个更好!)

import subprocess
result = subprocess.run(['python', 'other.py'], stdout=subprocess.PIPE)

或者这个(哪个更糟!)

import subprocess
result = subprocess.run('python other.py', stdout=subprocess.PIPE, shell=True)

如果您想要 运行 具有与 运行 当前脚本相同的 Python 可执行文件的脚本,请不要使用 python 并依赖路径设置正确,只需使用 sys.executable:

A string giving the absolute path of the executable binary for the Python interpreter, on systems where this makes sense.

如果您使用 python myscript.py 依赖于活动 virtualenv 的 PATH 执行脚本,这将起作用。如果您使用 /usr/local/bin/python3.6 执行脚本以忽略 PATH 并使用特定的解释器测试您的脚本,它也会起作用。或者,如果您使用 myscript.py 执行脚本,依赖于 setuptools 在安装时创建的 shbang 行。或者如果脚本是 运行 作为 CGI,具体取决于您的 Apache 配置。或者,如果您 sudod 了可执行文件,或者做了其他破坏您环境的事情。或者几乎任何其他可以想象的东西。1

中所述,您仍然需要使用参数列表而不是字符串(或使用 shell=True,但您很少想这样做)。所以:

result = subprocess.run([sys.executable, 'other.py'], stdout=subprocess.PIPE)

1.嗯,不完全是......它 工作的例子包括嵌入 CPython 解释器的自定义 C 程序,一些智能手机迷你 Python 环境,旧的-school Amiga Python, … 最有可能影响你的是——这是一个相当大的延伸——是在一些 *nix 平台上,如果你写的程序 execs Python通过为进程和 arg0 传递不兼容的名称,sys.executable 可能会出错。