Содержание страницы
queue – синхронизированный класс очереди¶queue – A synchronized queue class
Исходный код: Lib/queue.py
Модуль queue реализует очереди с несколькими производителями и несколькими потребителями.
Особенно полезно в многопоточном программировании, когда нужно безопасно обмениваться данными между несколькими потоками. Класс Queue в этом модуле реализует всю необходимую семантику блокировок.
Модуль реализует три типа очередей, различающихся только порядком извлечения элементов. В очереди FIFO первые добавленные задачи извлекаются первыми. В очереди LIFO последний добавленный элемент извлекается первым (работает как стек). В очереди с приоритетом элементы хранятся отсортированными (с помощью модуля heapq), и элемент с наименьшим значением извлекается первым.
Внутри этих трёх типов очередей для временной блокировки конкурирующих потоков используются блокировки; однако они не рассчитаны на реентерабельность в пределах одного потока.
Кроме того, модуль реализует «простой» тип очереди FIFO, SimpleQueue, чья реализация предоставляет дополнительные гарантии ценой меньшей функциональности.
Модуль queue определяет следующие классы и исключения:
- class queue.Queue(maxsize=0)¶
Конструктор для очереди FIFO. maxsize – целое число, задающее верхний предел количества элементов, которые можно поместить в очередь. Вставка будет блокироваться, когда этот размер достигнут, пока элементы очереди не будут потреблены. Если maxsize меньше или равно нулю, размер очереди бесконечен.
- class queue.LifoQueue(maxsize=0)¶
Конструктор для очереди LIFO. maxsize – целое число, задающее верхний предел количества элементов, которые можно поместить в очередь. Вставка будет блокироваться, когда этот размер достигнут, пока элементы очереди не будут потреблены. Если maxsize меньше или равно нулю, размер очереди бесконечен.
- class queue.PriorityQueue(maxsize=0)¶
Конструктор для очереди с приоритетом. maxsize – целое число, задающее верхний предел количества элементов, которые можно поместить в очередь. Вставка будет блокироваться, когда этот размер достигнут, пока элементы очереди не будут потреблены. Если maxsize меньше или равно нулю, размер очереди бесконечен.
Элементы с наименьшим значением извлекаются первыми (элемент с наименьшим значением – это тот, который вернула бы функция
min(entries)). Обычно элементы представлены кортежем вида:(priority_number, data).Если элементы data несравнимы, данные можно обернуть в класс, который игнорирует элемент данных и сравнивает только номер приоритета:
from dataclasses import dataclass, field from typing import Any @dataclass(order=True) class PrioritizedItem: priority: int item: Any=field(compare=False)
- class queue.SimpleQueue¶
Конструктор для неограниченной очереди FIFO. Простые очереди лишены расширенной функциональности, такой как отслеживание задач.
Простые очереди являются обобщёнными по типу своих элементов.
Добавлено в версии 3.7.
- exception queue.Empty¶
Исключение, возбуждаемое при вызове неблокирующего
get()(илиget_nowait()) на пустом объектеQueue.
- exception queue.Full¶
Исключение, возбуждаемое при вызове неблокирующего
put()(илиput_nowait()) на полном объектеQueue.
- exception queue.ShutDown¶
Исключение, возбуждаемое при вызове
put()илиget()на объектеQueue, который был закрыт.Добавлено в версии 3.13.
Объекты очередей¶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)¶
Помещает элемент в очередь. Если необязательный аргумент block истинен и timeout равен
None(по умолчанию), блокируется при необходимости до освобождения места. Если timeout – положительное число, блокируется не более чем на timeout секунд и возбуждает исключениеFull, если за это время место не освободилось. В противном случае (block ложен), помещает элемент в очередь, если место свободно немедленно, иначе возбуждает исключениеFull(в этом случае timeout игнорируется).Вызывает
ShutDown, если очередь была закрыта.
- Queue.put_nowait(item)¶
Эквивалентно
put(item, block=False).
- Queue.get(block=True, timeout=None)¶
Удаляет элемент из очереди и возвращает его. Если необязательный аргумент block равен true, а timeout равен
None(по умолчанию), при необходимости блокирует выполнение, пока элемент не станет доступен. Если timeout – положительное число, блокирует выполнение не более чем на timeout секунд и вызывает исключениеEmpty, если за это время элемент не появился. В противном случае (block равен false) возвращает элемент, если он доступен немедленно, иначе вызывает исключениеEmpty(timeout в этом случае игнорируется).До версии 3.0 в системах POSIX и во всех версиях Windows, если block истинен и timeout равен
None, эта операция переходит в непрерываемое ожидание на базовой блокировке. Это означает, что никакие исключения не могут возникнуть, и, в частности, SIGINT не вызоветKeyboardInterrupt.Возбуждает
ShutDown, если очередь была закрыта и пуста, или если очередь была закрыта немедленно.
- Queue.get_nowait()¶
Эквивалентно
get(block=False).
Предлагаются два метода для отслеживания того, были ли задачи, поставленные в очередь, полностью обработаны потоками-потребителями-демонами.
- Queue.task_done()¶
Указывает, что ранее поставленная в очередь задача завершена. Используется потоками-потребителями очереди. Для каждого вызова
get(), использованного для получения задачи, последующий вызовtask_done()сообщает очереди, что обработка задачи завершена.Если
join()в данный момент заблокирован, он возобновит работу, когда все элементы будут обработаны (то есть для каждого элемента, который былput()в очередь, был получен вызовtask_done()).Возбуждает
ValueError, если вызывается больше раз, чем было помещено элементов в очередь.
- Queue.join()¶
Блокируется до тех пор, пока все элементы в очереди не будут получены и обработаны.
Счётчик незавершённых задач увеличивается каждый раз, когда элемент добавляется в очередь. Счётчик уменьшается, когда поток-потребитель вызывает
task_done(), чтобы указать, что элемент был получен и вся работа с ним завершена. Когда счетчик незавершённых задач падает до нуля,join()разблокируется.
Ожидание завершения задач¶Waiting for task completion
Пример ожидания завершения поставленных в очередь задач:
import threading
import queue
q = queue.Queue()
def worker():
while True:
item = q.get()
print(f'Working on {item}')
print(f'Finished {item}')
q.task_done()
# Запустить рабочий поток.
threading.Thread(target=worker, daemon=True).start()
# Отправить рабочему тридцать запросов задач.
for item in range(30):
q.put(item)
# Ожидать завершения всех задач.
q.join()
print('All work completed')
Завершение работы очередей¶Terminating queues
Когда больше не нужны, объекты Queue можно постепенно завершить до опустошения или немедленно остановить с помощью жёсткого завершения.
- Queue.shutdown(immediate=False)¶
Переводит экземпляр
Queueв режим завершения работы.Очередь больше не может расти. Будущие вызовы
put()возбуждаютShutDown. Текущие заблокированные вызывающиеput()будут разблокированы и возбудятShutDownв ранее заблокированном потоке.Если immediate равен false (значение по умолчанию), очередь можно завершить нормально с помощью вызовов
get()для извлечения задач, которые уже были загружены.И если
task_done()вызывается для каждой оставшейся задачи, ожидающий вызовjoin()будет разблокирован нормально.Как только очередь опустеет, последующие вызовы
get()будут возбуждать исключениеShutDown.Если immediate равен true, очередь завершается немедленно. Очередь опустошается полностью, и счётчик незавершённых задач уменьшается на количество извлечённых задач. Если незавершённых задач нет, вызывающие
join()разблокируются. Также блокированные вызывающиеget()разблокируются и возбудят исключениеShutDown, так как очередь пуста.Соблюдайте осторожность при использовании
join()с параметром immediate, установленным в true. Это разблокирует join, даже если над задачами не было проделано никакой работы, нарушая обычный инвариант ожидания завершения очереди.Добавлено в версии 3.13.
Объекты SimpleQueue¶SimpleQueue Objects
Объекты SimpleQueue предоставляют описанные ниже публичные методы.
- SimpleQueue.qsize()¶
Возвращает приблизительный размер очереди. Обратите внимание, qsize() > 0 не гарантирует, что последующий вызов get() не заблокируется.
- SimpleQueue.empty()¶
Возвращает
True, если очередь пуста, иFalseв противном случае. Если empty() возвращаетFalse, это не гарантирует, что последующий вызов get() не заблокируется.
- SimpleQueue.put(item, block=True, timeout=None)¶
Помещает элемент в очередь. Метод никогда не блокируется и всегда выполняется успешно (за исключением возможных низкоуровневых ошибок, например, сбоя выделения памяти). Необязательные аргументы block и timeout игнорируются и предоставлены только для совместимости с
Queue.put().Особенность реализации CPython: Этот метод имеет реализацию на C, которая является реентерабельной. То есть вызов
put()илиget()может быть прерван другим вызовомput()в том же потоке без взаимоблокировки или повреждения внутреннего состояния очереди. Это делает его подходящим для использования в деструкторах, таких как методы__del__или колбэкиweakref.
- SimpleQueue.put_nowait(item)¶
Эквивалентно
put(item, block=False), предусмотрено для совместимости сQueue.put_nowait().
- SimpleQueue.get(block=True, timeout=None)¶
Удаляет элемент из очереди и возвращает его. Если необязательный аргумент block равен true, а timeout равен
None(по умолчанию), при необходимости блокирует выполнение, пока элемент не станет доступен. Если timeout – положительное число, блокирует выполнение не более чем на timeout секунд и вызывает исключениеEmpty, если за это время элемент не появился. В противном случае (block равен false) возвращает элемент, если он доступен немедленно, иначе вызывает исключениеEmpty(timeout в этом случае игнорируется).
- SimpleQueue.get_nowait()¶
Эквивалентно
get(False).
См. также
- Класс
multiprocessing.Queue Класс очереди для использования в контексте многопроцессорной обработки (а не многопоточности).
collections.deque – это альтернативная реализация неограниченных очередей с быстрыми атомарными операциями append() и popleft(), которые не требуют блокировок и также поддерживают индексирование.