在多个进程之间共享结果队列

时间:2012-03-28 13:42:59

标签: python parallel-processing queue multiprocessing python-multiprocessing

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限制)。但如何我是如何以有效的方式传递队列的呢?我找不到一个例子,我尝试了几种以各种方式失败的替代品。请帮忙吗?

2 个答案:

答案 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.QueueManager.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来解除等待父的阻塞。