10

キューがいつ閉じられ、それ以上のアイテムがなくなるかを知る必要があるため、反復を終了できます。

センチネルをキューに入れることでそれを行いました:

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

これがキューの非常に一般的な用途であることを考えると、組み込みの実装はありませんか?

4

3 に答える 3

14

センチネルは、これ以上キュー タスクが実行されないというメッセージをプロデューサーが送信するための合理的な方法です。

FWIW、 iter()の 2 つの引数形式を使用すると、コードをかなり単純化できます。

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)
于 2012-07-02T06:08:34.047 に答える
4

multiprocessing モジュールには、メソッドを含む独自のバージョンの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 をキャッチできます。

テスト

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.
于 2012-07-02T05:41:46.893 に答える