【发布时间】:2012-11-08 07:44:40
【问题描述】:
我有一组命令行工具,我想在一系列文件上并行运行。我编写了一个 python 函数来包装它们,看起来像这样:
def process_file(fn):
print os.getpid()
cmd1 = "echo "+fn
p = subprocess.Popen(shlex.split(cmd1))
# after cmd1 finishes
other_python_function_to_do_something_to_file(fn)
cmd2 = "echo "+fn
p = subprocess.Popen(shlex.split(cmd2))
print "finish"
if __name__=="__main__":
import multiprocessing
p = multiprocessing.Pool()
for fn in files:
RETURN = p.apply_async(process_file,args=(fn,),kwds={some_kwds})
虽然这可行,但它似乎并没有运行多个进程;似乎它只是串行运行(我尝试使用 Pool(5) 得到相同的结果)。我错过了什么?对Popen 的调用是否“阻塞”?
编辑:澄清一点。我需要 cmd1,然后是一些 python 命令,然后是 cmd2,以便在每个文件上按顺序执行。
EDIT2:上面的输出具有以下模式:
pid
finish
pid
finish
pid
finish
而类似的调用,使用map 代替apply(但没有任何传递kwds 的规定)看起来更像
pid
pid
pid
finish
finish
finish
但是,map 调用有时(总是?)在明显成功后挂起
【问题讨论】:
-
在回答这个问题之前……你为什么需要
multiprocessing?您可以在一个进程中创建一大堆Popen实例,它们将与您在多个进程中创建它们一样并行。 -
嗯,这是我的问题的一部分(感谢您帮助我澄清)...我的 shell 命令需要连续运行(即 cmd1、cmd2、cmd3)。我希望对每个文件执行每个 series。
-
@abarnert 是对的。只是不要在进程上调用
communicate或wait -
嗯,
map正在等待所有孩子完成后才返回,而apply_async立即返回。如果您不想在所有作业完成之前阻止,请使用map_async或imap_unordered。但我认为在这种情况下,你确实想阻止,对吧?无论如何,在您的用例中,我不确定简化调度的好处是否超过了包装函数调用的复杂性,所以我不知道您需要在这部分进行多长时间。 -
至于
map挂……你确定所有的工作都完成了吗?这实际上是调试的痛苦……但是如果您切换到imap_unordered,您可以获得更多关于正在发生的事情的反馈。 (multiprocessing.Pool的代码非常简单——看一下。)