Как работает запуск корутин в asyncio?

Изучаю асинхронное программирование, и возникли вопросы.

Есть корутина, эмулирующая ввод данных:

import asyncio 
from time import time, sleep


async def waste_time():
    print("Start work...")
    await asyncio.sleep(2)
    print("End work!")

Она запускается в корутине main(), с которой у меня и возникает вопрос, ее описание будет ниже.

Запуск скрипта осуществляется следующим образом:

if __name__ == '__main__':
    start = time()
    asyncio.run(main())
    print(time() - start)

Я хочу запустить 10 функций waste_time(). Но я не могу понять, почему такой код выполняется как положено:

async def main():
    tasks = []

    for _ in range(10):
        task = asyncio.create_task(waste_time())
        tasks.append(task)

    for task in tasks:
        await task
$ python3 main.py
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
End work!
End work!
End work!
End work!
End work!
End work!
End work!
End work!
End work!
End work!
2.005629301071167

А такой - нет:

async def main():
    tasks = []

    for _ in range(10):
        task = asyncio.create_task(waste_time())
        tasks.append(task)
        await task

Start work...
End work!
Start work...
End work!
Start work...
End work!
Start work...
End work!
Start work...
End work!
Start work...
End work!
Start work...
End work!
Start work...
End work!
Start work...
End work!
Start work...
End work!
20.023030042648315

Предположительно, суть в том, что я в первом случае сначала все запустил, а потом ожидаю выполнения, а во втором ожидаю выполнения после каждого конкретно запуска.

Не могли бы вы описать подробнее этот процесс? Я изучал асинхронность сначала на генераторах(yield from, модуль selectors, делегирующие генераторы и подгенераторы), потом библиотеку asyncio. Ощущение, будто я упускаю что-то очевидное.

Также почему получается такой вывод: введите сюда описание изображения Разве он не должен идти в таком порядке:

Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
Start work...
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
старт
End work!
финиш
2.0058696269989014

Ответы (1 шт):

Автор решения: eri

Все очень просто.

Корутины запускаются в том месте где написано следующее слово await. В первом варианте вы набили в массив незапущенных корутин и потом запустили всех в один момент (ожидание первой)

Точнее чуть сложнее именно в этом случае. Первая запустилась на первом авэйте. Вторая запустилась на авэйте который внутри первой, третья запустилась на авэйте внутри второй. Если бы не было внутреннего авэйта, то запустились бы по очереди всей толпой в первом попавшемся.

Во втором варианте вы ожидаете первую, а потом создаете вторую.

В третьем варианте печатается start/end в начале потому что они все успели выполниться во время ожидания первой . порядок правильный - один старт спереди.

Но это касается только тасков.

Корутины которые не являются фьючерсами - запускаются когда авэйтишь именно их.

→ Ссылка