听起来你的问题开始于你试图通过将它作为参数传递来共享一个multiprocessing.Queue()。您可以通过创建managed queue来解决这个问题:import multiprocessing
manager = multiprocessing.Manager()
passable_queue = manager.Queue()
当您使用管理器创建它时,您正在存储一个代理并将其传递给队列,而不是队列本身,因此即使传递给工作进程的对象是复制的,它仍将指向相同的底层数据结构:队列。它与(C/C++)中的指针非常类似(概念上)。如果以这种方式创建队列,则可以在启动工作进程时传递它们。
由于现在可以传递队列,因此不再需要管理字典。在main中保留一个普通的字典,它将存储所有映射,并且只为您的工作进程提供它们需要的队列,因此它们不需要访问任何映射。
我在这里写了一个例子。看起来你在工作人员之间传递对象,所以这里就是这样做的。假设我们有两个处理阶段,数据在main的控制下开始和结束。看看我们如何创建像管道一样连接工人的队列,但是通过只给他们他们需要的队列,他们不需要知道任何映射:import multiprocessing as mp
def stage1(q_in, q_out):
q_out.put(q_in.get()+"Stage 1 did some work.\n")
return
def stage2(q_in, q_out):
q_out.put(q_in.get()+"Stage 2 did some work.\n")
return
def main():
pool = mp.Pool()
manager = mp.Manager()
# create managed queues
q_main_to_s1 = manager.Queue()
q_s1_to_s2 = manager.Queue()
q_s2_to_main = manager.Queue()
# launch workers, passing them the queues they need
results_s1 = pool.apply_async(stage1, (q_main_to_s1, q_s1_to_s2))
results_s2 = pool.apply_async(stage2, (q_s1_to_s2, q_s2_to_main))
# Send a message into the pipeline
q_main_to_s1.put("Main started the job.\n")
# Wait for work to complete
print(q_s2_to_main.get()+"Main finished the job.")
pool.close()
pool.join()
return
if __name__ == "__main__":
main()
代码生成此输出:Main started the job.
Stage 1 did some work.
Stage 2 did some work.
Main finished the job.
我没有在字典中包含存储队列或AsyncResults对象的示例,因为我仍然不太理解您的程序应该如何工作。但是现在您可以自由地传递队列了,您可以根据需要构建字典来存储队列/进程映射。
事实上,如果您真的在多个worker之间构建了一个管道,那么您甚至不需要在main中保留对“inter worker”队列的引用。创建队列,将其传递给工作人员,然后只保留对main将使用的队列的引用。如果您确实有“任意数量”的队列,我绝对建议您尝试让旧队列尽快被垃圾回收。