我有一个程序使用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
但我得到了错误,好像我没有抓到异常。捕获的正确例外是什么?
答案 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()吗?