【发布时间】:2017-12-24 00:14:48
【问题描述】:
我实际上很难相信我遇到了我遇到的问题,这似乎是 python 多处理模块中的一个大错误......无论如何我遇到的问题是每当我将 multiprocessing.Queue 作为参数传递给 multiprocessing.Pool 工作者时,池工作者永远不会执行其代码。即使是在 python docs 中找到的示例代码的略微修改版本的非常简单的测试中,我也能够重现此错误。
这是队列示例代码的原始版本:
from multiprocessing import Process, Queue
def f(q):
q.put([42, None, 'hello'])
if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
print(q.get()) # prints "[42, None, 'hello']"
p.join()
这是我对队列示例代码的修改版本:
from multiprocessing import Queue, Pool
def f(q):
q.put([42, None, 'hello'])
if __name__ == '__main__':
q = Queue()
p = Pool(1)
p.apply_async(f,args=(q,))
print(q.get()) # prints "[42, None, 'hello']"
p.close()
p.join()
我所做的只是让 p 成为大小为 1 的进程池,而不是 multiprocessing.Process 对象,结果是代码永远挂在 print 语句上,因为没有任何东西写入队列!当然,我以原始形式对此进行了测试,并且效果很好。我的操作系统是 windows 10,我的 python 版本是 3.5.x,有人知道为什么会这样吗?
更新:仍然不知道为什么此示例代码适用于 multiprocessing.Process 而不是 multiprocessing.Pool 但我找到了 work around 我很满意(Alex Martelli 的回答)。显然,您可以只创建一个 multiprocessing.Queues 的全局列表并传递每个进程和索引以供使用,我将避免使用托管队列,因为它们速度较慢。感谢客人向我展示链接。
【问题讨论】:
-
请注意,使用异步编程您不需要手动处理结果队列 -
apply_async返回一个AsyncResult实例,可用于获取结果:result.get()。这使用了一个底层的结果(out-)队列,所以你只需要在你的目标函数中return。此外,如果您使用result.get()并将Queue实例作为参数传递给目标函数,它将引发RuntimeError。但是我很好奇为什么您的示例没有发生这种情况。 -
查看我对您的回答的评论。我的目标不是“结果队列”,这只是一个简单的例子。我需要一个不断写入和处理的队列。
标签: python python-3.x python-multiprocessing