这是我的代码,它应该做的事与this other question尝试做的非常相似,特别是这个图是相关的: f1 =产生,f2 = f3 =工人,f4 =消费者。
我还没有尝试过很好地结束一切的问题,这不是这个问题的内容。我收到错误“RuntimeError:队列对象只应通过继承在进程之间共享” 我不知道该怎么做才能解决它。我只是想把队列传递给Go的频道,真的。这是代码。
import multiprocessing
def produce(n, queue):
for i in xrange(n):
queue.put(i)
def worker(in_queue, out_queue):
for i in iter( in_queue.get, None):
out_queue.put(i*i)
def consumer(queue):
ans = []
for i in iter( queue.get, None):
ans.append(i)
return ans
def main(n):
pool = multiprocessing.Pool(4)
in_queue = multiprocessing.Queue()
out_queue = multiprocessing.Queue()
pool.apply_async(produce, (n, in_queue))
for i in range(2):
pool.apply_async(worker, (in_queue, out_queue))
result = consumer(out_queue)
pool.close()
pool.join()
return result
main(200)
我该如何修复它?
有更简单的方法吗?
我已经尝试Pool.map
,但我想让它发挥作用。
答案 0 :(得分:2)
multiprocessing.Pool
已经设置了必要的IPC机制,允许您在工作启动后向其工作人员提交作业,但您不能在以后作为参数传递ist a Queue或类似工具。这就是你的代码不起作用的原因。在启动子进程时,它必须知道如何与其父进程通信。
因此,如果您需要设置自己的队列,则应直接使用multiprocessing.Process
。此外,你所写的是典型的工人,他们在一个循环中等待新工作并处理它们。在工人池中运行这样的工人不是你想要做的事情。
这样你的代码就可以了:
import multiprocessing
def produce(n, queue):
for i in xrange(n):
queue.put(i)
def worker(in_queue, out_queue):
for i in iter( in_queue.get, None):
out_queue.put(i*i)
def consumer(queue):
ans = []
for i in iter( queue.get, None):
print(i)
ans.append(i)
return ans
def main(n):
in_queue = multiprocessing.Queue()
out_queue = multiprocessing.Queue()
producer = multiprocessing.Process(target=produce, args=(n, in_queue))
for i in range(2):
w = multiprocessing.Process(target=worker, args=(in_queue, out_queue))
w.start()
producer.start()
res = consumer(out_queue)
main(200)
我在consumer
中添加了一个打印声明,表明发生了一些事情。 consumer
函数永远不会终止,因为你从队列中读取的代码会等待一个永远不会出现的终止None
,因为工作者和生产者都没有把它放入队列......
答案 1 :(得分:0)
使用multiprocessing.Manager
可以跨池化进程共享队列。我更新了OP的代码以使用pool.apply_async
方法。为此,我使用None
来指示进程方法中的任务完成,并添加代码以等待main方法中异步调用的完成。
import multiprocessing
def produce(n, queue):
for i in xrange(n):
queue.put(i)
# None indicates termination / completion
queue.put(None)
def worker(in_queue, out_queue):
while True:
i = in_queue.get()
if i is None:
# Put the None back for other workers listening to the queue to see
in_queue.put(None)
out_queue.put(None)
return
out_queue.put(i*i)
def consumer(queue):
ans = []
while True:
i = queue.get()
if i is None:
queue.put(None)
return ans
ans.append(i)
def main(n):
manager = multiprocessing.Manager()
in_queue = manager.Queue()
out_queue = manager.Queue()
pool = multiprocessing.Pool(4)
async_results = []
ar = pool.apply_async(produce, (n, in_queue))
async_results.append(ar)
for i in range(2):
ar = pool.apply_async(worker, (in_queue, out_queue))
async_results.append(ar)
ar = pool.apply_async(consumer, (out_queue,))
async_results.append(ar)
for ar in async_results:
ar.wait()
result = async_results[len(async_results)-1].get()
print(result)
pool.close()
pool.join()
return result
if __name__ == "__main__":
main(200)