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 меньше или равно нулю, размер очереди бесконечен.
Элементы с наименьшими значениями извлекаются первыми (элемент с наименьшим значением — тот, который был бы возвращен
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, который заполнен.
Объекты очереди
Объекты очереди (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 истинны и timeout —
None, заблокировать, если необходимо, до тех пор, пока не появится свободное место. Если timeout — положительное число, блокировать не более timeout секунд и возбудить исключениеFull, если свободное место не было доступно в течение этого времени. В противном случае (block ложно), поместить элемент в очередь, если свободное место доступно немедленно, иначе возбудить исключениеFull(timeout игнорируется в этом случае).
-
Queue.put_nowait(item) -
Эквивалентно
put(item, block=False).
-
Queue.get(block=True, timeout=None) -
Удалить и вернуть элемент из очереди. Если необязательные аргументы block истинны и timeout —
None, заблокировать, если необходимо, до тех пор, пока не станет доступен элемент. Если timeout — положительное число, блокировать не более timeout секунд и возбудить исключениеEmpty, если элемент не был доступен в течение этого времени. В противном случае (block ложно), вернуть элемент, если он доступен немедленно, иначе возбудить исключениеEmpty(timeout игнорируется в этом случае).До версии 3.0 на системах POSIX и для всех версий на Windows, если block истинно и 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
import 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)
# 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) -
Поместить элемент в очередь. Метод никогда не блокируется и всегда выполняется успешно (за исключением потенциальных ошибок низкого уровня, таких как невозможность выделения памяти). Необязательные аргументы 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 ложно), вернуть элемент, если он сразу доступен, иначе вызвать исключениеEmpty(timeout игнорируется в этом случае).
-
SimpleQueue.get_nowait() -
Эквивалентно
get(False).
См. также
-
Classmultiprocessing.Queue -
Класс очереди для использования в контексте многопроцессорной (а не многопоточной) обработки.
collections.deque — это альтернативная реализация неограниченных очередей с быстрыми атомарными операциями append() и popleft(), которые не требуют блокировки, а также поддерживают индексирование.
© 2001–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.11/library/queue.html