关于python:并行运行子进程

run subprocesses in parallel

我有一个python脚本,它必须调用某个应用程序3次。这些呼叫应该是Parralel,因为它们需要几个小时才能完成,并且不依赖于彼此。但脚本应该停止,直到所有脚本都完成,然后执行一些清理工作。

下面是一些代码:

1
2
3
4
5
6
7
8
9
10
#do some stuff

for work in worklist:   # these should run in parralel
    output=open('test.txt','w')
    subprocess.call(work,stdout=output,stderr=output)
    output.close()

# wait for subprocesses to finish

# cleanup

所以我基本上想在parrelel中运行这个命令,同时将它的输出捕获到一个文件中。完成所有实例后,我希望继续脚本


subprocess.call()正在阻塞。这意味着,在继续之前,每个调用都必须等待子进程完成。

您需要的是将参数传递给subprocess.Popen构造函数。这样,您的子进程将在不阻塞的情况下启动。

稍后,您可以通过调用Popen.communicate()Popen.wait()将这些子进程连接在一起。

1
2
3
4
5
6
7
8
9
child_processes = []
for work, filename in worklist:
    with io.open(filename, mode='wb') as out:
        p = subprocess.Popen(work, stdout=out, stderr=out)
        child_processes.append(p)    # start this one, and immediately return to start another

# now you can join them together
for cp in child_processes:
    cp.wait()                         # this will block on each child process until it exits

另外,您是否查阅过python关于subprocess模块的文档?


我喜欢在这种情况下使用GNU Parallel(http://www.gnu.org/software/parallel/),因为它提供了一种快速获得并行性的方法,并且有许多选项,包括在结束时重新组织输出,使所有输出按顺序从每个进程流到一起,但不交错。您还可以指定一次要运行的编号,或者指定一个特定的编号,或者指定与您拥有的核心数量匹配的编号,它将把其余的命令排队。

只需使用subprocess.check_outputshell=True就可以使用命令字符串调用parallel。如果您有一个要插入的变量,比如一个要对其运行命令的SQL表的列表,parallel也擅长处理这个问题——您可以用参数输入文本文件的内容。

如果所有命令都完全不同(而不是同一命令的变体),则将完整的命令放在您导入parallel的文本文件中。

您也不需要做任何特殊的事情来等待它们完成,因为check_output调用将阻塞,直到parallel命令完成。