Сообщить об ошибке.

Функция as_completed() модуля asyncio в Python

Получение результатов работы сопрограмм в реальном времени

Синтаксис:

import asyncio

asyncio.as_completed(aws, *, loop=None, timeout=None)

Параметры:

Возвращаемое значение:

  • возвращает итератор с результатами работы задач.

Описание asyncio.as_completed:

Функция as_completed() модуля asyncio одновременно запускает объекты awaitable, переданные в итерации aws, ждет их выполнения и по готовности любого начинает возвращать готовые объекты Future.

Другими словами, функция asyncio.as_completed() запускает и ждет выполнения переданных в нее задач/awaitable-объектов, и как только появляются результаты у какой-нибудь задачи, в реальном времени, начинает возвращать их в итераторе. Результаты извлекаются, запуском каждого объекта итератора при помощи оператора await.

Например:

for coro in as_completed(aws):
    earliest_result = await coro
    # ...

Аргумент timeout (float или int) в секундах, если он указан, можно использовать для управления максимальным временем ожидания, перед тем, как остановить не выполненные задачи, оставшихся в итераторе aws.

Вызывает исключение asyncio.TimeoutError, если тайм-аут наступает до того, как все задачи/awaitable-объекты будут выполнены.

Изменено в Python 3.8: аргумент loop устарел и будет удален в Python 3.10.

Изменено в Python 3.10: удален аргумент loop.

Устарело, начиная с Python 3.10: выдается предупреждение об устаревании, если не все ожидаемые объекты в aws являются объектами, подобными Future, и нет запущенного цикла событий.

Изменено в Python 3.12: добавлена поддержка генераторов, выдающих задания.

Пример получения результатов из сопрограмм в реальном времени.

import asyncio, time

async def worker(delay, name):
    # эмитируем ожидание какого-то ответа 
    # ответа от стороннего сервиса
    await asyncio.sleep(delay)
    # возвращаем результат
    return name, delay

async def main():
    # список аргументов для `worker()``
    targets = [(0.5, 'one'), (0.8, 'two'), 
          (0.2, 'three'), (1, 'four'), (0.5, 'five')]
    
    # создаем задачи
    tasks = [asyncio.create_task(worker(*target)) for target in targets]
    
    # передаем задачи в функцию `as_completed()`
    for future in asyncio.as_completed(tasks):
        # получаем результаты по готовности 
        res = await future
        # выводим на печать
        print(f'Задача: {res[0]}; задержка: {res[1]}')
        
if __name__ == '__main__':
    start = time.time()
    # запускаем цикл событий
    asyncio.run(main())
    
    total = time.time() - start
    print(f'Общее время выполнения: {total:.3f} сек.')

# Задача: three; задержка: 0.2
# Задача: one; задержка: 0.5
# Задача: five; задержка: 0.5
# Задача: two; задержка: 0.8
# Задача: four; задержка: 1
# Общее время выполнения: 1.001 сек.

Попробуйте в функцию передать значение таймаута, сначала 0.8 секунды - asyncio.as_completed(tasks, dalay=0.8), а потом 1.1 секунды и проследить поведение программы.