2017-04-16 508 views
10

我有一个简单的任务,这样的:Python的multiprocessing.Queue VS multiprocessing.manager()队列()

def worker(queue): 
    while True: 
     try: 
      _ = queue.get_nowait() 
     except Queue.Empty: 
      break 

if __name__ == '__main__': 
    manager = multiprocessing.Manager() 
    # queue = multiprocessing.Queue() 
    queue = manager.Queue() 

    for i in range(5): 
     queue.put(i) 

    processes = [] 

    for i in range(2): 
     proc = multiprocessing.Process(target=worker, args=(queue,)) 
     processes.append(proc) 
     proc.start() 

    for proc in processes: 
     proc.join() 

似乎multiprocessing.Queue能做到这一点,我需要所有的工作,但在另我看到很多manager()的例子,Queue()并不能理解我真正需要的东西。看起来像Manager()。Queue()使用某种代理对象,但我不理解这些目的,因为multiprocessing.Queue()在没有任何代理对象的情况下执行相同的工作。

所以,我的问题是:

1)什么是真正的差异multiprocessing.Queue和物体之间通过multiprocessing.manager()返回队列()?

2)我需要使用什么?

+3

这可能有帮助。 https://code.activestate.com/lists/python-tutor/99586/ –

回答

8

虽然我的理解是有限的关于这个主题,从我做什么我可以告诉有multiprocessing.Queue()和multiprocessing.Manager()之间的一个主要区别是队列():

  • 多。 Queue()是一个对象,而multiprocessing.Manager()。Queue()是指向由multiprocessing.Manager()对象管理的共享队列的地址(代理)。
  • 因此,您无法将正常的multiprocessing.Queue()对象传递给池方法,因为它不能被酸洗。
  • 此外,该python doc告诉我们使用multiprocessing.Queue()时要特别注意,因为它可能具有不希望影响

注意当一个对象被放在一个队列,对象酸洗后台线程稍后将清理的数据刷新到底层管道。这有一些令人惊讶的后果,但不应该导致任何实际困难 - 如果他们真的打扰你,那么你可以使用由经理创建的队列。 将对象置于空队列后,可能会在队列的empty()方法返回False之前存在无限小的延迟,并且get_nowait()可能会返回而不会引发Queue.Empty。 如果有多个进程将对象排入队列,那么有可能在另一端无序地接收对象。然而,由相同过程入队的对象将始终按预期顺序相对于彼此。

警告正如上面提到的,如果一个子进程已经把项目一个队列(它没有使用JoinableQueue.cancel_join_thread),那么该过程将不会终止,直到所有的缓存项已经刷新到管道。 这意味着如果您尝试加入该进程,则可能会发生死锁,除非您确定放入队列中的所有项目都已被使用。同样,如果子进程是非守护进程,那么父进程在尝试加入所有非守护进程子进程时可能会在退出时挂起。 请注意,使用管理器创建的队列不存在此问题。

有通过设置队列作为全局变量和初始化设置它为所有进程使用multiprocessing.Queue()配有游泳池的一种变通方法:

queue = multiprocessing.Queue() 
def initialize_shared(q): 
    global queue 
    queue=q 

pool= Pool(nb_process,initializer=initialize_shared, initargs(queue,)) 

将创建池的过程与正确共享队列,但我们可以争辩说multiprocessing.Queue()对象不是为这个用途而创建的。

另一方面,manager.Queue()可以通过传递它作为函数的普通参数在池子进程之间共享。

在我看来,使用multiprocessing.Manager()。Queue()在每种情况下都很好,并且不那么麻烦。使用经理可能会有一些缺点,但我不知道。