在python的多处理中检查空队列

时间:2011-08-18 14:30:25

标签: python queue multiprocessing

我有一个程序使用python的包多处理和队列。我的一个功能有这个结构:

from multiprocessing import Process, Queue
def foo(queue):
   while True:
       try:
           a = queue.get(block = False)
           doAndPrintStuff(a)
       except:
           print "the end"
           break

   if __name__ == "__main__"
     nthreads = 4
     queue = Queue.Queue()
     # put stuff in the queue here 
     for stuff in moreStuff:
         queue.put(stuff)
     procs = [Process(target = foo, args = (queue,)) for i in xrange(nthreads)]
     for p in procs:
       p.start()
     for p in procs:
       p.join()

我的想法是,当我尝试从队列中提取并且它为空时,它将引发异常并终止循环。所以我有两个问题:

1)这是一个安全的习惯用法吗?有更好的方法吗?

2)我试图找到当我从空队列中尝试.get()时引发的确切异常。目前我的程序正在捕获所有异常,当错误发生在其他地方时很糟糕,我只收到“结束”消息。

我试过了:

  import Queue
  queue = Queue.Queue()
  [queue.put(x) for x in xrange(10)]
  try: 
       print queue.get(block = False)
  except Queue.Empty:
       print "end"
       break

但我得到了错误,好像我没有抓到异常。捕获的正确例外是什么?

3 个答案:

答案 0 :(得分:14)

例外应为Queue.Empty。但是你确定你有相同的错误吗?在第二个示例中,您还将队列本身从multiprocessing.Queue切换为Queue.Queue,我认为这可能是问题所在。

这可能看起来很奇怪,但您必须使用multiprocessing.Queue类,但使用Queue.Empty例外(必须从Queue模块中导入)

答案 1 :(得分:2)

在刷新put缓冲区之前,Queue似乎是空的,这可能需要一段时间。

我们问题的解决方案是to use sentinels,或者内置task_done()来电:

  

task_done()

     

表示以前排队的任务已完成。由队列使用者线程使用。对于用于获取任务的每个get(),后续   对task_done()的调用告诉队列该任务的处理是   完整。

     

如果join()当前正在阻止,它将在所有项目都已处理后恢复(意味着收到了task_done()调用   已放入队列的每个项目。

     

如果调用的次数超过队列中放置的项目,则引发ValueError。

答案 2 :(得分:-3)

尝试阅读queue图书馆文档。你不是在寻找Queue.empty()吗?