使用队列时等待Python进程完成的简单而安全的方法
我正在使用使用队列时等待Python进程完成的简单而安全的方法,python,Python,我正在使用Process类来创建和管理子流程,这些子流程可能会返回非平凡的数据量。文档中指出,join()是等待过程完成的正确方法() 但是,当使用多处理.Queue时,这可能会在加入进程后导致挂起,如下所述:和此处(不是错误) 这些文档建议删除p.join()——但这肯定会取消所有进程都已完成的保证,因为Queue.get()只等待单个项目可用 在这种情况下,我如何等待所有过程的完成,并确保我正在收集所有过程的输出 我想处理的一个简单的挂起示例: from multiprocessing im
Process
类来创建和管理子流程,这些子流程可能会返回非平凡的数据量。文档中指出,join()
是等待过程完成的正确方法()
但是,当使用多处理.Queue
时,这可能会在加入进程后导致挂起,如下所述:和此处(不是错误)
这些文档建议删除p.join()
——但这肯定会取消所有进程都已完成的保证,因为Queue.get()
只等待单个项目可用
在这种情况下,我如何等待所有过程的完成,并确保我正在收集所有过程的输出
我想处理的一个简单的挂起示例:
from multiprocessing import Process, Queue
class MyClass:
def __init__(self):
pass
def example_run(output):
output.put([MyClass() for i in range(1000)])
print("Bottom of example_run() - note hangs after this is printed")
if __name__ == '__main__':
output = Queue()
processes = [Process(target=example_run, args=(output,)) for x in range(5)]
for p in processes:
p.start()
for p in processes:
p.join()
print("Processes completed")
这意味着,无论何时使用队列,都需要确保
所有放在队列上的项目最终都将被删除
在加入流程之前。否则你不能确定
已将项目放入队列的进程将终止
在您的示例中,在调用join()
之前,我刚刚添加了output.get()
,一切正常。我们将数据放入队列,以便在某些地方使用,所以请确保
for p in processes:
p.start()
print output.get()
for p in processes:
p.join()
print("Processes completed")
一个不雅观的解决方案是添加
output_final = []
for i in range(5): # we have 5 processes
output_final.append(output.get())
在尝试加入任何进程之前。这只是尝试为我们已启动的进程数量获得适当数量的输出
一个更好、更广泛的解决方案是根本不使用过程
;使用池
。这样,您就可以解决启动辅助进程和收集结果的麻烦:
import multiprocessing
class MyClass:
def __init__(self):
pass
def example_run(someArbitraryInput):
foo = [MyClass() for i in range(10000)]
return foo
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=5)
output = pool.map(example_run, range(5))
pool.close(); pool.join() # make sure the processes are complete and tidy
print("Processes completed")
感谢您的回复@AlokThakur。我不完全清楚output.get()
行是如何工作的-这会等待所有引用队列的进程完成吗?文件对此不清楚。我需要保证我不会看到这样的情况:一个进程比其他进程花费的时间长得多,结果会丢失(或者它仍然挂在join()
@Giswok output.get()上。等到有东西进入队列时,它不会等待进程。您可以在output.get(timeout)中提到超时。因此,如果没有进程将任何数据放入队列,则将使用此超时。您应该阅读更多有关有效使用队列的信息。问题8426建议,如果进程将大数据放入队列,请确保在加入进程之前获取数据。是的,不幸的是,队列中的文档确实不是很清楚。我们仍然没有找到直接等待所有数据的方法进程完成,但如果在join()
:output\u final=[]
,用于范围内的i(nr\u进程):output\u final.append(output.get())
这看起来很不雅观。output.get()也是如此
本身就是一个阻塞调用,如果派生进程中的所有信息都在派生进程生命周期的最后被推送到队列中,那么只需使用output.get()
而不需要加入就可以了吗?