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 — false), вернуть элемент, если он сразу доступен, иначе вызвать исключение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.10/library/queue.html