multiprocessing
模块的文档显示了如何将队列传递给以multiprocessing.Process
开头的进程。但是,如何与以apply_async
开头的异步工作进程共享队列?我不需要动态加入或其他任何东西,只是让工人(反复)将结果报告回基地的方式。
import multiprocessing
def worker(name, que):
que.put("%d is done" % name)
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=3)
q = multiprocessing.Queue()
workers = pool.apply_async(worker, (33, q))
这失败了:
RuntimeError: Queue objects should only be shared between processes through inheritance
。
我理解这意味着什么,我理解继承的建议,而不是要求pickle / unpickling(以及所有特殊的Windows限制)。但如何我是如何以有效的方式传递队列的呢?我找不到一个例子,我尝试了几种以各种方式失败的替代品。请帮忙吗?
答案 0 :(得分:101)
尝试使用multiprocessing.Manager来管理您的队列,并让不同的工作人员可以访问它。
import multiprocessing
def worker(name, que):
que.put("%d is done" % name)
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=3)
m = multiprocessing.Manager()
q = m.Queue()
workers = pool.apply_async(worker, (33, q))
答案 1 :(得分:0)
multiprocessing.Pool
已经有一个共享的结果队列,不需要另外涉及Manager.Queue
。 Manager.Queue
是位于内部的queue.Queue
(多线程队列),位于单独的服务器进程上,并通过代理公开。与Pool的内部队列相比,这会增加额外的开销。
此外,工作进程不是以.apply_async()
开始,而是在实例化Pool
时发生。什么是
当您致电pool.apply_async()
时,这是一个新的“工作”。 Pool的工作进程在后台运行multiprocessing.pool.worker
函数。此函数负责处理通过Pool内部Pool._inqueue
传输的新“任务”,并通过Pool._outqueue
将结果发送回父级。您指定的func
将在multiprocessing.pool.worker
中执行。 func
只需return
东西,结果就会自动发送回父级。
.apply_async()
立即(异步)返回一个AsyncResult
对象(ApplyResult
的别名)。您需要在该对象上调用.get()
(正在阻塞)以接收实际结果。另一种选择是注册一个callback函数,该函数会在结果准备好后立即触发。
from multiprocessing import Pool
def busy_foo(i):
"""Dummy function simulating cpu-bound work."""
for _ in range(int(10e6)): # do stuff
pass
return i
if __name__ == '__main__':
with Pool(4) as pool:
print(pool._outqueue) # DEMO
results = [pool.apply_async(busy_foo, (i,)) for i in range(10)]
# `.apply_async()` immediately returns AsyncResult (ApplyResult) object
print(results[0]) # DEMO
results = [res.get() for res in results]
print(f'result: {results}')
示例输出:
<multiprocessing.queues.SimpleQueue object at 0x7fa124fd67f0>
<multiprocessing.pool.ApplyResult object at 0x7fa12586da20>
result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
注意:为timeout
指定.get()
参数不会停止在工作程序中实际执行任务,只会通过引发multiprocessing.TimeoutError
来解除等待父的阻塞。