Документация Python неофициальный перевод
Содержание страницы

17.7. queue – Синхронизированная очередьqueue – A synchronized queue class

Исходный код: Lib/queue.py


Модуль queue реализует очереди с несколькими производителями и потребителями. Он особенно полезен в многопоточном программировании, когда необходимо безопасно обмениваться данными между несколькими потоками. Класс Queue в этом модуле реализует всю необходимую семантику блокировок. Для работы требуется поддержка потоков в Python; см. модуль threading.

Модуль реализует три типа очередей, которые различаются только порядком извлечения элементов. В очереди FIFO первыми извлекаются задачи, добавленные первыми. В очереди LIFO последний добавленный элемент извлекается первым (работает как стек). В очереди с приоритетом элементы поддерживаются отсортированными (с помощью модуля heapq), и первым извлекается элемент с наименьшим значением.

Модуль queue определяет следующие классы и исключения:

class queue.Queue(maxsize=0)

Конструктор очереди FIFO. maxsize – целое число, которое задает верхнюю границу количества элементов, которые можно поместить в очередь. Вставка будет блокироваться, как только этот размер достигнут, пока элементы очереди не будут потреблены. Если maxsize меньше или равно нулю, размер очереди бесконечен.

class queue.LifoQueue(maxsize=0)

Конструктор очереди LIFO. maxsize – целое число, которое задает верхнюю границу количества элементов, которые можно поместить в очередь. Вставка будет блокироваться, как только этот размер достигнут, пока элементы очереди не будут потреблены. Если maxsize меньше или равно нулю, размер очереди бесконечен.

class queue.PriorityQueue(maxsize=0)

Конструктор для очереди с приоритетом. maxsize – целое число, задающее верхний предел количества элементов, которые можно поместить в очередь. Вставка будет блокироваться, когда этот размер достигнут, пока элементы очереди не будут потреблены. Если maxsize меньше или равно нулю, размер очереди бесконечен.

Элементы с наименьшим значением извлекаются первыми (элемент с наименьшим значением – это то, что возвращает sorted(list(entries))[0]). Типичный шаблон для элементов – кортеж вида: (priority_number, data).

exception queue.Empty

Исключение, которое возникает при вызове неблокирующего get() (или get_nowait()) для пустого объекта Queue.

exception queue.Full

Исключение, которое возникает при вызове неблокирующего put() (или put_nowait()) для полного объекта Queue.

17.7.1. Объекты очередиQueue Objects

Объекты очереди (Queue, LifoQueue или PriorityQueue) предоставляют описанные ниже публичные методы.

Queue.qsize()

Возвращает приблизительный размер очереди. Обратите внимание: qsize() > 0 не гарантирует, что последующий вызов get() не заблокируется, равно как qsize() < maxsize не гарантирует, что put() не заблокируется.

Queue.empty()

Возвращает True, если очередь пуста, и False в противном случае. Если empty() возвращает True, это не гарантирует, что последующий вызов put() не будет блокироваться. Аналогично, если empty() возвращает False, это не гарантирует, что последующий вызов get() не будет блокироваться.

Queue.full()

Возвращает True, если очередь полна, и False в противном случае. Если full() возвращает True, это не гарантирует, что последующий вызов get() не будет блокироваться. Аналогично, если full() возвращает False, это не гарантирует, что последующий вызов put() не будет блокироваться.

Queue.put(item, block=True, timeout=None)

Помещает item в очередь. Если необязательный аргумент block равен true, а timeout равен None (значение по умолчанию), при необходимости блокируется до появления свободного места. Если timeout – положительное число, блокируется не более чем на timeout секунд и возбуждает исключение Full, если свободное место не появилось за это время. В противном случае (block равен false) помещает элемент в очередь, если свободное место есть немедленно; иначе возбуждает исключение Full (в этом случае timeout игнорируется).

Queue.put_nowait(item)

Эквивалентно put(item, False).

Queue.get(block=True, timeout=None)

Удаляет и возвращает элемент из очереди. Если необязательный аргумент block равен true и timeout равен None (по умолчанию), при необходимости блокируется до появления элемента. Если timeout – положительное число, он блокируется не более чем на timeout секунд и возбуждает исключение Empty, если за это время элемент не появился. В противном случае (block равен false) возвращает элемент, если он доступен немедленно; иначе возбуждает исключение Empty (в этом случае timeout игнорируется).

Queue.get_nowait()

Эквивалентно get(False).

Предлагаются два метода для отслеживания того, были ли задачи, поставленные в очередь, полностью обработаны потоками-потребителями-демонами.

Queue.task_done()

Указывает, что ранее поставленная задача выполнена. Используется потоками-потребителями очереди. Для каждого get(), используемого для получения задачи, последующий вызов task_done() сообщает очереди, что обработка задачи завершена.

Если join() в данный момент блокируется, он возобновит работу, когда все элементы будут обработаны (то есть вызов task_done() был получен для каждого элемента, который был помещён в очередь с помощью put()).

Возбуждает ValueError, если вызывается больше раз, чем было помещено элементов в очередь.

Queue.join()

Блокируется до тех пор, пока все элементы в очереди не будут получены и обработаны.

Счётчик незавершённых задач увеличивается каждый раз, когда элемент добавляется в очередь. Счётчик уменьшается каждый раз, когда поток-потребитель вызывает task_done(), чтобы указать, что элемент извлечён и вся работа над ним завершена. Когда счётчик незавершённых задач падает до нуля, join() разблокируется.

Пример ожидания завершения поставленных в очередь задач:

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.daemon = True
     t.start()

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

q.join()       # ожидать завершения всех задач

См. также

Класс multiprocessing.Queue
Класс очереди для использования в контексте многопроцессорной обработки (а не многопоточности).

collections.deque – это альтернативная реализация неограниченных очередей с быстрыми атомарными операциями append() и popleft(), не требующими блокировки.