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

时间:2018-05-31 19:34:49

标签: python subprocess virtualenv

我有一个名为'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命令?

2 个答案:

答案 0 :(得分:3)

子进程无法在其父进程中运行命令,而无需该进程的参与。

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

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

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

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

subprocess.run必须通过列表,或者必须使用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)

答案 1 :(得分:1)

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

  

一个字符串,给出Python解释器的可执行二进制文件的绝对路径,在有意义的系统上。

如果您使用python myscript.py依赖于活动的virtualenv的PATH执行脚本,则此方法有效。如果您使用/usr/local/bin/python3.6执行脚本以忽略PATH并使用特定解释器测试脚本,它也可以工作。或者,如果您使用myscript.py执行脚本,则依赖于setuptools在安装时创建的shbang行。或者,如果脚本是作为CGI运行的,则取决于您的Apache配置。或者,如果您sudo执行可执行文件,或者执行了其他可能会破坏您的环境的内容。或几乎任何其他可以想象到的东西。 1

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

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

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