我需要知道何时关闭队列并且不会有更多项目,所以我可以结束迭代。
我是通过在队列中放置一个标记来实现的:
from Queue import Queue
class IterableQueue(Queue):
_sentinel = object()
def __iter__(self):
return self
def close(self):
self.put(self._sentinel)
def next(self):
item = self.get()
if item is self._sentinel:
raise StopIteration
else:
return item
鉴于这是一个非常常见的队列使用,是不是有任何内置实现?
答案 0 :(得分:12)
生成器是一种合理的方式,可以让生产者发送不再有队列任务的消息。
FWIW,您的代码可以使用iter()的两个参数形式进行简化:
from Queue import Queue
class IterableQueue(Queue):
_sentinel = object()
def __iter__(self):
return iter(self.get, self._sentinel)
def close(self):
self.put(self._sentinel)
答案 1 :(得分:4)
多处理模块有自己的Queue版本,其中包含close
方法。我不确定它在线程中是如何工作的,但值得一试。我不明白为什么不应该这样做:
from multiprocessing import Queue
q = Queue()
q.put(1)
q.get_nowait()
# 1
q.close()
q.get_nowait()
# ...
# IOError: handle out of range in select()
您可以将IOError作为关闭信号捕获。
<强> TEST 强>
from multiprocessing import Queue
from threading import Thread
def worker(q):
while True:
try:
item = q.get(timeout=.5)
except IOError:
print "Queue closed. Exiting thread."
return
except:
continue
print "Got item:", item
q = Queue()
for i in xrange(3):
q.put(i)
t = Thread(target=worker, args=(q,))
t.start()
# Got item: 0
# Got item: 1
# Got item: 2
q.close()
# Queue closed. Exiting thread.
虽然说实话,但它与在Queue.Queue上设置标志没什么不同。 multiprocessing.Queue只是使用一个封闭的文件描述符作为标志:
from Queue import Queue
def worker2(q):
while True:
if q.closed:
print "Queue closed. Exiting thread."
return
try:
item = q.get(timeout=.5)
except:
continue
print "Got item:", item
q = Queue()
q.closed = False
for i in xrange(3):
q.put(i)
t = Thread(target=worker2, args=(q,))
t.start()
# Got item: 0
# Got item: 1
# Got item: 2
q.closed = True
# Queue closed. Exiting thread.