QueuesОчереди
Исходный код: Lib/asyncio/queues.py
Очереди asyncio спроектированы так, чтобы быть похожими на классы модуля queue. Хотя очереди asyncio не являются потокобезопасными, они предназначены для использования именно в async/await коде.
Обратите внимание, что методы очередей asyncio не имеют параметра timeout; используйте функцию asyncio.wait_for() для выполнения операций с очередью с тайм-аутом.
Смотрите также раздел Примеры ниже.
QueueОчередь
- class asyncio.Queue(maxsize=0)¶
Очередь «первым вошёл – первым вышел» (FIFO).
Если maxsize меньше или равно нулю, размер очереди бесконечен. Если это целое число больше
0, тоawait put()блокируется, когда очередь достигает maxsize, пока элемент не будет удалён вызовомget().В отличие от
queueиз стандартной библиотеки threading, размер очереди всегда известен и может быть получен вызовом методаqsize().Изменено в версии 3.10: Удалён параметр loop.
Этот класс является не потокобезопасным.
- maxsize¶
Количество элементов, допустимое в очереди.
- empty()¶
Возвращает
True, если очередь пуста,Falseв противном случае.
- full()¶
Возвращает
True, если в очереди естьmaxsizeэлементов.Если очередь была инициализирована с
maxsize=0(по умолчанию), тоfull()никогда не возвращаетTrue.
- async get()¶
Удаляет и возвращает элемент из очереди. Если очередь пуста, ждёт, пока элемент не станет доступен.
Возбуждает
QueueShutDown, если очередь была закрыта и пуста, или если очередь была закрыта немедленно.
- get_nowait()¶
Возвращает элемент, если он немедленно доступен, иначе возбуждает
QueueEmpty.
- async join()¶
Блокируется до тех пор, пока все элементы в очереди не будут получены и обработаны.
Счётчик незавершённых задач увеличивается при каждом добавлении элемента в очередь. Счётчик уменьшается, когда корутина-потребитель вызывает
task_done(), чтобы указать, что элемент был получен и вся работа над ним завершена. Когда счётчик незавершённых задач падает до нуля,join()разблокируется.
- async put(item)¶
Помещает элемент в очередь. Если очередь полна, ждёт, пока не освободится место, прежде чем добавить элемент.
Возбуждает
QueueShutDown, если очередь была закрыта.
- put_nowait(item)¶
Помещает элемент в очередь без блокировки.
Если свободный слот недоступен, вызывает
QueueFull.
- qsize()¶
Возвращает количество элементов в очереди.
- shutdown(immediate=False)¶
Переводит экземпляр
Queueв режим завершения работы.Очередь больше не может расти. Последующие вызовы
put()вызываютQueueShutDown. Текущие заблокированные вызывающиеput()будут разблокированы и вызовутQueueShutDownв ранее ожидающей задаче.Если immediate равен false (по умолчанию), очередь может быть нормально завершена с помощью вызовов
get()для извлечения задач, которые уже были загружены.И если
task_done()вызывается для каждой оставшейся задачи, ожидающаяjoin()будет разблокирована нормально.Как только очередь станет пуста, последующие вызовы
get()будут вызыватьQueueShutDown.Если immediate равен true, очередь завершается немедленно. Очередь опустошается полностью, и количество незавершённых задач уменьшается на количество опустошённых задач. Если незавершённых задач нет, вызывающие
join()разблокируются. Кроме того, заблокированные вызывающиеget()разблокируются и вызовутQueueShutDown, поскольку очередь пуста.Будьте осторожны при использовании
join()с immediate, установленным в true. Это разблокирует ожидание завершения (join) даже если над задачами не было выполнено никакой работы, нарушая обычный инвариант присоединения к очереди.Добавлено в версии 3.13.
- task_done()¶
Указывает, что ранее помещённый в очередь элемент работы завершён.
Используется потребителями очереди. Для каждого
get(), используемого для получения элемента работы, последующий вызовtask_done()сообщает очереди, что обработка элемента работы завершена.Если
join()в данный момент заблокирован, он возобновится, когда все элементы будут обработаны (то есть для каждого элемента, который былput()в очередь, был получен вызовtask_done()).Вызывает
ValueError, если вызван большее количество раз, чем было элементов, помещённых в очередь.
Priority QueueОчередь с приоритетом
LIFO QueueОчередь LIFO
ExceptionsИсключения
- exception asyncio.QueueEmpty¶
Это исключение вызывается, когда метод
get_nowait()вызывается на пустой очереди.
- exception asyncio.QueueFull¶
Исключение вызывается, когда метод
put_nowait()вызывается на очереди, которая достигла своего maxsize.
ExamplesПримеры
Очереди могут использоваться для распределения рабочей нагрузки между несколькими одновременными задачами:
import asyncio
import random
import time
async def worker(name, queue):
while True:
# Взять «элемент работы» из очереди.
sleep_for = await queue.get()
# Уснуть на «sleep_for» секунд.
await asyncio.sleep(sleep_for)
# Уведомить очередь, что «элемент работы» обработан.
queue.task_done()
print(f'{name} has slept for {sleep_for:.2f} seconds')
async def main():
# Создать очередь для хранения нашей «нагрузки».
queue = asyncio.Queue()
# Сгенерировать случайные временные интервалы и поместить их в очередь.
total_sleep_time = 0
for _ in range(20):
sleep_for = random.uniform(0.05, 1.0)
total_sleep_time += sleep_for
queue.put_nowait(sleep_for)
# Создать три задачи-обработчика для параллельной обработки очереди.
tasks = []
for i in range(3):
task = asyncio.create_task(worker(f'worker-{i}', queue))
tasks.append(task)
# Дождаться полной обработки очереди.
started_at = time.monotonic()
await queue.join()
total_slept_for = time.monotonic() - started_at
# Отменить наши рабочие задачи.
for task in tasks:
task.cancel()
# Дождаться отмены всех рабочих задач.
await asyncio.gather(*tasks, return_exceptions=True)
print('====')
print(f'3 workers slept in parallel for {total_slept_for:.2f} seconds')
print(f'total expected sleep time: {total_sleep_time:.2f} seconds')
asyncio.run(main())