queue — Класс синхронизированной очереди
Исходный код: 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 меньше или равно нулю, размер очереди бесконечен.
Элементы с наименьшим значением извлекаются первыми (элемент с наименьшим значением — это тот, который возвращает
sorted(list(entries))[0]). Типичный шаблон для элементов — кортеж в формате:(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, который заполнен.
Объекты очереди
Объекты очереди (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 игнорируется в этом случае).До версии 3.0 на системах POSIX и во всех версиях на Windows, если block равно true и timeout равно
None, эта операция переходит в непрерывающий ожидание на базовой блокировке. Это означает, что исключения не могут произойти, и в частности, SIGINT не вызоветKeyboardInterrupt.
-
Queue.get_nowait() -
Эквивалентно
get(False).
Предлагаются два метода для отслеживания того, были ли задачи, помещенные в очередь, полностью обработаны демоновыми потоками-потребителями.
-
Queue.task_done() -
Указывает, что задача, ранее помещенная в очередь, завершена. Используется потоками-потребителями очереди. Для каждого вызова
get()для получения задачи, последующий вызовtask_done()сообщает очереди, что обработка задачи завершена.Если
join()в настоящее время заблокирован, он возобновится, когда все элементы будут обработаны (что означает, что вызовtask_done()был получен для каждого элемента, который былput()в очередь).Вызывает
ValueError, если вызван большее количество раз, чем было помещено элементов в очередь.
-
Queue.join() -
Блокируется, пока все элементы в очереди не будут извлечены и обработаны.
Счет незавершенных задач увеличивается всякий раз, когда элемент добавляется в очередь. Счет уменьшается всякий раз, когда поток-потребитель вызывает
task_done()для указания того, что элемент был извлечен и вся работа над ним завершена. Когда счет незавершенных задач уменьшается до нуля,join()разблокируется.
Пример того, как дождаться завершения задач в очереди:
import threading, queue
q = queue.Queue()
def worker():
while True:
item = q.get()
print(f'Working on {item}')
print(f'Finished {item}')
q.task_done()
# turn-on the worker thread
threading.Thread(target=worker, daemon=True).start()
# send thirty task requests to the worker
for item in range(30):
q.put(item)
print('All task requests sent\n', end='')
# block until all tasks are done
q.join()
print('All work completed')
Объекты SimpleQueue
SimpleQueue предоставляют описанные ниже публичные методы.
-
SimpleQueue.qsize() -
Возвращает приблизительный размер очереди. Обратите внимание, что qsize() > 0 не гарантирует, что последующий вызов get() не заблокируется.
-
SimpleQueue.empty() -
Возвращает
True, если очередь пуста, иFalseв противном случае. Если empty() возвращаетFalse, это не гарантирует, что последующий вызов get() не заблокируется.
-
SimpleQueue.put(item, block=True, timeout=None) -
Поместить item в очередь. Метод никогда не блокируется и всегда выполняется успешно (кроме потенциальных ошибок низкого уровня, таких как неудача в выделении памяти). Дополнительные аргументы block и timeout игнорируются и предоставляются только для совместимости с
Queue.put().Подробность реализации CPython: Этот метод имеет реализацию на C, которая является реентерабельной. То есть вызов
put()илиget()может быть прерван другим вызовомput()в том же потоке без возникновения тупика или повреждения внутреннего состояния внутри очереди. Это делает его подходящим для использования в деструкторах, таких как методы__del__илиweakrefобратные вызовы.
-
SimpleQueue.put_nowait(item) -
Эквивалентно
put(item), предоставляется для совместимости сQueue.put_nowait().
-
SimpleQueue.get(block=True, timeout=None) -
Удалить и вернуть элемент из очереди. Если необязательный аргумент block равен true и timeout равен
None(по умолчанию), заблокировать, если необходимо, до тех пор, пока элемент не станет доступен. Если timeout является положительным числом, блокировка происходит не более timeout секунд, и если элемент не был доступен в течение этого времени, генерируется исключениеEmpty. В противном случае (block ложно), вернуть элемент, если он сразу доступен, иначе сгенерировать исключениеEmpty(timeout игнорируется в этом случае).
-
SimpleQueue.get_nowait() -
Эквивалентно
get(False).
См. также
-
Classmultiprocessing.Queue -
Класс очереди для использования в контексте многопроцессорной (а не многопоточной) обработки.
collections.deque — альтернативная реализация неограниченных очередей с быстрыми атомными операциями append() и popleft(), которые не требуют блокировки, а также поддерживают индексирование.
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/queue.html