运行 shell 命令在一个 shell 与子进程中顺序执行

Running shell commands sequentially in one shell with subprocess

我在使用 subprocess 模块执行一系列顺序命令时遇到困难 运行,我需要这样做以便 python 程序可以调用安装 cv virtualenv 然后 运行 另一个 python 程序(需要在 virtualenv 中 运行)

这是来自终端的命令字符串 i 运行,您可以看到它包含多个命令 运行 顺序,直到创建 cv 虚拟环境:

sudo pip install virtualenv virtualenvwrapper && sudo rm -rf ~/.cache/pip && export WORKON_HOME=$HOME/.virtualenvs && source /usr/local/bin/virtualenvwrapper.sh && source ~/.bashrc && mkvirtualenv cv

运行 这个在终端里 returns 我是这样的:

(cv) name@computer:~$ 

由此我可以 运行 我的 python 脚本需要 openCV

到目前为止我的代码是这样的:

from subprocess import Popen, PIPE, STDOUT

cmd1 = 'sudo pip install virtualenv virtualenvwrapper'
cmd2 = 'sudo rm -rf ~/.cache/pip'
cmd3 = 'export WORKON_HOME=$HOME/.virtualenvs'
cmd4 = 'source /usr/local/bin/virtualenvwrapper.sh'
cmd5 = 'source ~/.bashrc'
cmd6 = 'mkvirtualenv cv'
cmd7 = 'cd /script path'
cmd8 = 'python novo.py'


final = Popen("{}; {}; {}; {}; {}; {}; {}; {}".format(cmd1, cmd2,cmd3,    cmd4, cmd5, cmd6, cmd7, cmd8), shell=True, stdin=PIPE, 
      stdout=PIPE, stderr=STDOUT, close_fds=True)

stdout, nothing = final.communicate()
log = open('log', 'w')
log.write(stdout)
log.close()

日志中的错误如下所示:

/bin/sh: 1: source: not found
/bin/sh: 1: source: not found
/bin/sh: 1: mkvirtualenv: not found

如何实现类似执行的终端? 同样,顺序很重要。

/bin/sh: 1: source: not found

shell=True 默认使用 /bin/shsource shell 内置提示 bash。通过 executable='/bin/bash'.

顺便说一句,您可以使用多行字符串文字:

#!/usr/bin/env python3
import sys
from subprocess import check_call, DEVNULL, STDOUT

with open('log', 'wb', 0) as file:
   check_call("""set -e -x
{python} -mpip install --user virtualenv virtualenvwrapper
rm -rf ~/.cache/pip
export WORKON_HOME=$HOME/.virtualenvs
source /path/to/virtualenvwrapper.sh
source ~/.bashrc
mkvirtualenv cv
cd /script path
{python} novo.py
""".format(python=sys.executable),
              shell=True, executable='/bin/bash',
              stdin=DEVNULL, stdout=file, stderr=STDOUT, close_fds=True)

或者将命令保存到单独的 bash 脚本中,然后 运行 脚本。

DEVNULL 是 Python 3 的特性——在 Python 2 上也很容易模拟它:DEVNULL = open(os.devnull, 'r+b', 0).