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

Python 如何获取当前shell并在其中执行命令?,python,subprocess,virtualenv,Python,Subprocess,Virtualenv,我有一个名为'venv'的virtualenv,它是激活的: (venv)> 我编写了代码,我将在virtualenv中运行它(main.py): 但是当我运行main.py文件时: (venv)> python main.py subprocess不在virtualenv中执行命令(python other.py),即venv 如何在当前virtualenv会话中运行子进程命令?如果没有父进程的参与,子进程无法在其父进程中运行命令。 这就是为什么ssh-agent需要使用ase

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

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

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

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

如何在当前virtualenv会话中运行
子进程
命令?

如果没有父进程的参与,子进程无法在其父进程中运行命令。 这就是为什么
ssh-agent
需要使用as
eval“$(ssh-agent-s)”
来调用它在输出时发出的shell命令。因此,你在这里要求的文字是不可能的

幸运的是,这也是不必要的


VirtualNV使用子进程继承的环境变量。 这意味着您实际上不需要使用激活了virtualenv的同一个shell来启动一个新的Python解释器,该解释器打算从该virtualenv使用解释器/库等


必须向
子流程.run
传递列表,或者必须使用
shell=True
。 要么这样做(哪一个更好!)

或者这个(哪个更糟!)


如果要使用运行当前脚本所用的相同Python可执行文件运行脚本,请不要使用
Python
,而是依赖正确设置的路径,只需使用:

在有意义的系统上,为Python解释器提供可执行二进制文件的绝对路径的字符串

如果使用
python myscript.py
依赖于活动virtualenv的路径来执行脚本,则此操作有效。如果使用
/usr/local/bin/python3.6
执行脚本,忽略路径并使用特定的解释器测试脚本,则该方法也会起作用。或者,如果使用
myscript.py
执行脚本,依赖于安装时由
setuptools
创建的shbang行。或者脚本是否作为CGI运行取决于您的Apache配置。或者,如果你
sudo
d了可执行文件,或者做了其他事情,破坏了你的环境。或者几乎任何其他可以想象的东西

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



一,。嗯,不完全是这样……它不起作用的例子包括嵌入CPython解释器的定制C程序、一些智能手机迷你Python环境、老式的Amiga Python……最有可能影响你的是,在一些*nix平台上,如果您通过为进程和arg0传递不兼容的名称来编写
exec
s Python的程序,
sys.executable
可能会以错误告终。

尝试:
subprocess.run(['Python','other.py',stdout=subprocess.PIPE)
?您不能调用“当前”shell中的某些内容,如果您指的是启动程序的shell。这是父进程。任何新程序的创建总是生成一个子流程;如果不允许您修改父进程,您就不能修改它。也就是说,您的
subprocess.run
代码按照给定的方式被破坏,除非您将其设置为
subprocess.run(['python',other.py'])
或使用
shell=True
(您不应该这样做):如问题中所述,它正在寻找一个名为
python other.py
、文件名中有空格的程序,而不是寻找一个名为
python
的程序,并向它传递一个
other.py
参数。@hadi,…你真的,真的不应该使用
shell=True
。如果您向以这种方式启动的程序传递参数,则很容易出现安全漏洞,除非非常小心。请参阅Python文档中的警告,说明为什么
shell=True
更糟糕?虽然这样做有效,但通常更好的答案是
sys.executable
。@hadi它可以很容易地打开安全漏洞。例如,如果使用以下代码:
import子流程;名称=输入(“名称?”);运行(f“echo Hi,{name},shell=True)
然后有人可以告诉用户键入
person;sudo rm-Rf/*
作为他们的名字,这将是一个有效的命令,因为整个字符串放在一起是
echo person;sudo rm-Rf/*
(UNIX中的sudo rm-Rf/*将递归删除计算机上所有可能的文件)。他们不能用
shell=False
这样做,因为它实际上不是在shell中运行的,所以这不可能发生。@abarnert,我同意。你会反对我把它编辑成我的答案吗,还是会使它与你的答案过度重复?(不过,作为社区维基,它并不是真正的“我的”答案,应该被认为可以在不需要任何许可的情况下进行编辑)
(venv)> python main.py
import subprocess
result = subprocess.run(['python', 'other.py'], stdout=subprocess.PIPE)
import subprocess
result = subprocess.run('python other.py', stdout=subprocess.PIPE, shell=True)
result = subprocess.run([sys.executable, 'other.py'], stdout=subprocess.PIPE)