目次

前のトピックへ

9.9. mutex — 排他制御

次のトピックへ

9.11. weakref — 弱参照

このページ

9.10. queue — 同期キュークラス

ノート

Queue モジュールは Python 3.0 で queue という名前に変更されました。 2to3 ツールは、自動的に import を変換します。

Queue モジュールは、多生産者-多消費者(multi-producer, multi-consumer)キューを実装します。 これは、複数のスレッドの間で情報を安全に交換しなければならないときのマルチスレッドプログラミングで特に有益です。 このモジュールの Queue クラスは、必要なすべてのロックセマンティクスを実装しています。 これはPythonのスレッドサポートの状況に依存します。 threading モジュールを参照してください。

3種類のキューが実装されていて、キューから取り出されるエントリの順番だけが違います。 FIFOキューでは、最初に追加されたエントリが最初に取り出されます。 LIFOキューでは、最後に追加されたエントリが最初に取り出されます(スタックのように振る舞います)。 優先順位付きキュー(priority queue)では、エントリは(heapq モジュールを利用して)ソートされ、 最も低い値のエントリが最初に取り出されます。

Queue モジュールは以下のクラスと例外を定義します:

class Queue.Queue(maxsize)

FIFOキューのコンストラクタです。 maxsize はキューに置くことのできる要素数の上限を設定する整数です。 いったんこの大きさに達したら、挿入はキューの要素が消費されるまでブロックされます。もし maxsize が0以下であるならば、キューの大きさは無限です。

class Queue.LifoQueue(maxsize)

LIFOキューのコンストラクタです。 maxsize はキューに置くことのできる要素数の上限を設定する整数です。 いったんこの大きさに達したら、挿入はキューの要素が消費されるまでブロックされます。もし maxsize が0以下であるならば、キューの大きさは無限です。

バージョン 2.6 で追加.

class Queue.PriorityQueue(maxsize)

優先順位付きキューのコンストラクタです。 maxsize はキューに置くことのできる要素数の上限を設定する整数です。 いったんこの大きさに達したら、挿入はキューの要素が消費されるまでブロックされます。もし maxsize が0以下であるならば、キューの大きさは無限です。

exception Queue.Empty

空な Queue オブジェクトで、非ブロックメソッドとして get() (または get_nowait()) が呼ばれたとき、送出される例外です。

exception Queue.Full

満杯な Queue オブジェクトで、非ブロックメソッドとして put() (または put_nowait()) が呼ばれたとき、送出される例外です。

参考

collections.deque は、ロックなしで popleft()append() といったアトミック操作が可能なキューの実装です。

9.10.1. キューオブジェクト

キューオブジェクト(Queue, LifoQueue, PriorityQueue)は、 以下のpublicメソッドを提供しています。

Queue.qsize()
Queue.empty()
Queue.full()
Queue.put(item[, block[, timeout]])

item をキューに入れます。もしオプション引数 block がTrueで timeout がNone(デフォルト)ならば、 フリースロットが利用可能になるまでブロックします。 timeout が正の値の場合、最大で timeout 秒間ブロックし、 その時間内に空きスロットが利用可能にならなければ、例外 Full を送出します。 他方(block がFalse)、直ちにフリースロットが利用できるならば、キューにアイテムを置きます。できないならば、例外 Full を送出します (この場合 timeout は無視されます)。

バージョン 2.3 で追加: timeout 引数が追加されました。

Queue.put_nowait(item)

put(item, False) と同じ意味です。

Queue.get([block[, timeout]])

キューからアイテムを取り除き、それを返します。もしオプション引数 block がTrueで timeout がNone(デフォルト)ならば、 アイテムが利用可能になるまでブロックします。もし timeout が正の値の場合、最大で timeout 秒間ブロックし、 その時間内でアイテムが利用可能にならなければ、例外 Empty を送出します。 他方(block がFalse)、直ちにアイテムが利用できるならば、それを返します。できないならば、例外 Empty を送出します (この場合 timeout は無視されます)。

バージョン 2.3 で追加: timeout 引数が追加されました。

Queue.get_nowait()

get(False) と同じ意味です。

キューに入れられたタスクが全て消費者スレッドに処理されたかどうかを追跡するために 2つのメソッドが提供されます。

Queue.task_done()

過去にキューに入れられたタスクが完了した事を示します。キューの消費者スレッドに利用されます。タスクの取り出しに使われた、各 get() に対して、それに続く task_done() の呼び出しは、取り出したタスクに対する処理が完了した事をキューに教えます。

join() がブロックされていた場合、全itemが処理された (キューに put() された全てのitemに対して task_done() が呼び出されたことを意味します) 時に復帰します。

キューにあるよりitemの個数よりも多く呼び出された場合、 ValueError が送出されます。

バージョン 2.5 で追加.

Queue.join()

キューの中の全アイテムが処理される間でブロックします。

キューにitemが追加される度に、未完了タスクカウントが増やされます。消費者スレッドが task_done() を呼び出して、itemを受け取ってそれに対する処理が完了した事を知らせる度に、未完了タスクカウントが減らされます。 未完了タスクカウントが0になったときに、join() のブロックが解除されます。

バージョン 2.5 で追加.

キューに入れたタスクが完了するのを待つ例:

def worker():
    while True:
        item = q.get()
        do_work(item)
        q.task_done()

q = Queue()
for i in range(num_worker_threads):
     t = Thread(target=worker)
     t.setDaemon(True)
     t.start()

for item in source():
    q.put(item)

q.join()       # 全タスクが完了するまでブロック