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 равен true, а timeout равен
None(значение по умолчанию), при необходимости блокирует выполнение до освобождения места. Если timeout — положительное число, блокирует выполнение не более чем на timeout секунд и вызывает исключениеFull, если за это время место не освободилось. В противном случае (если block равен false) помещает элемент в очередь, если свободное место доступно немедленно, иначе вызывает исключениеFull(в этом случае timeout игнорируется).
-
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 равен 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
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) -
Помещает item в очередь. Метод никогда не блокирует выполнение и всегда завершается успешно (за исключением возможных низкоуровневых ошибок, например невозможности выделить память). Необязательные аргументы 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/queue.html