Содержание страницы
Очереди¶Queues
Исходный код: Lib/asyncio/queues.py
Очереди asyncio разработаны по аналогии с классами
queue модуля. Хотя очереди asyncio не являются потокобезопасными,
они предназначены для использования именно в async/await коде.
Обратите внимание: методы очередей asyncio не имеют параметра тайм-аут;
используйте функцию asyncio.wait_for() для выполнения операций с очередью с тайм-аутом.
Смотрите также раздел Примеры ниже.
Очередь¶Queue
- class asyncio.Queue(maxsize=0)¶
Очередь «первым вошёл – первым вышел» (FIFO).
Если maxsize меньше или равен нулю, размер очереди бесконечен. Если это целое число больше
0, тоawait put()блокируется, когда очередь достигает maxsize пока элемент не будет удалён с помощьюget().В отличие от
queueиз стандартной библиотеки threading, размер очереди всегда известен и может быть получен вызовом методаqsize().Изменено в версии 3.10: Удалён параметр loop.
This class is не является потокобезопасным.
- maxsize¶
Количество элементов, которое может содержать очередь.
- empty()¶
Возвращает
True, если очередь пуста, иначеFalse.
- full()¶
Возвращает
True, если в очередиmaxsizeэлементов.Если очередь была инициализирована с
maxsize=0(по умолчанию), тоfull()никогда не возвращаетTrue.
- async get()¶
Удаляет элемент из очереди и возвращает его. Если очередь пуста, ожидает, пока элемент не станет доступен.
- get_nowait()¶
Возвращает элемент, если он доступен немедленно, в противном случае вызывает
QueueEmpty.
- async join()¶
Блокирует выполнение до тех пор, пока все элементы в очереди не будут получены и обработаны.
Счётчик незавершённых задач увеличивается при каждом добавлении элемента в очередь. Счётчик уменьшается, когда корутина-потребитель вызывает
task_done(), чтобы указать, что элемент был получен и вся работа над ним завершена. Когда счётчик незавершённых задач падает до нуля,join()разблокируется.
- async put(item)¶
Помещает элемент в очередь. Если очередь заполнена, ожидает, пока не появится свободное место, прежде чем добавить элемент.
- put_nowait(item)¶
Помещает элемент в очередь без блокировки.
Если свободный слот недоступен сразу, возбуждается исключение
QueueFull.
- qsize()¶
Возвращает количество элементов в очереди.
- task_done()¶
Указывает, что ранее помещённый в очередь элемент работы завершён.
Используется потребителями очереди. Для каждого вызова
get(), использованного для извлечения элемента работы, последующий вызовtask_done()сообщает очереди, что обработка элемента работы завершена.Если вызов
join()в данный момент заблокирован, он возобновится, когда все элементы будут обработаны (то есть для каждого помещённого в очередь элементаput()был получен вызовtask_done()).Возбуждает исключение
ValueError, если вызывается больше раз, чем было помещено элементов в очередь.
Приоритетная очередь¶Priority Queue
Очередь LIFO¶LIFO Queue
Исключения¶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())