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中运行这个命令,同时将它的输出捕获到一个文件中。完成所有实例后,我希望继续脚本
- 相关:python:并行运行子进程,python处理多个bash子进程,python:并行运行子进程。
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模块的文档?
- 如果随后的进程的stdout/stderr管道在for循环开始调用communication()之前填满,则可能会出现延迟的风险。一个简单的解决方案是将stdout/err传输到临时文件。
- 我可以直接将stdout和stderror链接到文件句柄吗?stdout=filehandle?也不应该是out,err=cp.communication()?
- 它们确实可以设置为现有的文件句柄。
- 如果我将它们直接路由到文本文件,我将如何等待进程完成?
- @是的。stdout=open('my-process-out.txt', 'w')工程。
- @prgmjunkie你可以打电话给p.wait(),在没有任何管道通信的情况下加入他们。
- 不过,我还有一个问题,如何使用stderr的相同句柄。我不能这样关闭文件?或者一旦结束它会自动关闭?
- @prgmjunkie我用open file handle更新了我的答案(with语句将自动关闭它。
- 非常感谢您的帮助,唯一的问题是,这会将所有命令的所有输出输出输出到单个文本文件中。我的工作列表实际上是一个dict列表,其中包含work命令和作为键值对的相应文件名。
- @prgmjunkie您可以很容易地修改我的示例代码来实现这一点。只需为循环的每个迭代打开一个新的文件句柄。
- 文件句柄之间不会有冲突吗?因为他们有相同的名字?
- 那就不要给他们起同样的名字。
- @那是吸毒者。也是为你做的。
我喜欢在这种情况下使用GNU Parallel(http://www.gnu.org/software/parallel/),因为它提供了一种快速获得并行性的方法,并且有许多选项,包括在结束时重新组织输出,使所有输出按顺序从每个进程流到一起,但不交错。您还可以指定一次要运行的编号,或者指定一个特定的编号,或者指定与您拥有的核心数量匹配的编号,它将把其余的命令排队。
只需使用subprocess.check_output和shell=True就可以使用命令字符串调用parallel。如果您有一个要插入的变量,比如一个要对其运行命令的SQL表的列表,parallel也擅长处理这个问题——您可以用参数输入文本文件的内容。
如果所有命令都完全不同(而不是同一命令的变体),则将完整的命令放在您导入parallel的文本文件中。
您也不需要做任何特殊的事情来等待它们完成,因为check_output调用将阻塞,直到parallel命令完成。
- shell=True几乎在任何情况下都是不安全的。
- 有潜在的问题,但在某些情况下肯定是好的。例如,输入不是来自外部网络的任意来源等。