如何获取当前 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 配置。或者,如果您 sudo
d 了可执行文件,或者做了其他破坏您环境的事情。或者几乎任何其他可以想象的东西。1
如 中所述,您仍然需要使用参数列表而不是字符串(或使用 shell=True
,但您很少想这样做)。所以:
result = subprocess.run([sys.executable, 'other.py'], stdout=subprocess.PIPE)
1.嗯,不完全是......它 不 工作的例子包括嵌入 CPython 解释器的自定义 C 程序,一些智能手机迷你 Python 环境,旧的-school Amiga Python, … 最有可能影响你的是——这是一个相当大的延伸——是在一些 *nix 平台上,如果你写的程序 exec
s Python通过为进程和 arg0 传递不兼容的名称,sys.executable
可能会出错。
我有一个名为 '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 配置。或者,如果您 sudo
d 了可执行文件,或者做了其他破坏您环境的事情。或者几乎任何其他可以想象的东西。1
如 shell=True
,但您很少想这样做)。所以:
result = subprocess.run([sys.executable, 'other.py'], stdout=subprocess.PIPE)
1.嗯,不完全是......它 不 工作的例子包括嵌入 CPython 解释器的自定义 C 程序,一些智能手机迷你 Python 环境,旧的-school Amiga Python, … 最有可能影响你的是——这是一个相当大的延伸——是在一些 *nix 平台上,如果你写的程序 exec
s Python通过为进程和 arg0 传递不兼容的名称,sys.executable
可能会出错。