Mail.ruПочтаМой МирОдноклассникиВКонтактеИгрыЗнакомстваНовостиКалендарьОблакоЗаметкиВсе проекты

Асинхронное программирование питон

Олег Дипникович Профи (740), на голосовании 1 месяц назад
Вопросы по коду.
1) в main() как работает event_loop? Он сначала построчно добавляет каждую задачу в event_loop и только потом, когда добавил, в том же порядке начинает их выполнять? То есть смотрит, что было добавлено первее, начинает выполнять, затем откладывает на время, в списке задач переходит к следующему методу и тд? А как только закончил выполнение определенной функции и видит, что уже прошло время, запускает снова нужную функцию. Всё верно или нет? Я просто не понимаю, он сначала все строки читает: заносит задачи в список, или он прочитал строку и сразу начал выполнение этой задачи.

2) Как работает asyncio .run? По сути, он добавляет в event_loop задачи, которые находятся в main(). И для задач, между которыми он может переключаться, await определена. Но что касается самого main()? Это ведь никакая не задача и в список задач event_loop его же не заносит? Или заносит..? То есть в run мы помещаем функцию, которая передастся как задача. Просто в эту задачу мы помещаем набор других задач, так?

В общем. Суть в том, что я не понял, как работает await. Если рассматривать main() как задачу аналогично есть вопросы: А что делает сам await? Вот выполняется первая задача asyncio.create_task(one()); Он доходит до await в one(), метод на время захлопывается? А как он потом вызывается, если основная задача - это main()? Или предусмотрена такая встройка функций? Если функция в main() - async, то она воспринимается как отдельная задача? Если да, то в целом всё ясно: начинается задача main(), выполняется первая строчка кода. one() - асинхронка, а значит добавляется отдельная задача в event_loop. Причём ставится на паузу пока что. Но у нас в event_loop из активных задач есть всё тот же main(), поэтому возвращаемся к main() и продолжаем исполнение. Так что ле?



 import asyncio 
import time

async def one():
print("Start one")
await asyncio.sleep(1)
print("Stop one")

async def two():
print("Start two")
await asyncio.sleep(2)
print("Stop two")

async def three():
print("Start three")
await asyncio.sleep(3)
print("Stop three")

async def main():
asyncio.create_task(one())
asyncio.create_task(two())
await asyncio.create_task(three())

if __name__=='__main__':
start = time.time()
asyncio.run(main())
print(time.time()-start)
Голосование за лучший ответ
Resurce InheiT Мастер (1089) 2 месяца назад
asyncio.run запускает event loop и создает главную задачу из main().

asyncio.create_task создает и запускает новые задачи, добавляя их в event loop.

await приостанавливает выполнение текущей корутины и отдает управление event loop-у.

Event loop следит за задачами, переключаясь между ними при await и возобновляя их выполнение.
Олег ДипниковичПрофи (740) 2 месяца назад
asyncio.create_task создает и запускает новые задачи
То есть строка asyncio.create_task(one()) запускает метод one() и добавляет его в event_loop да?

А как работает при этом основная задача main() ? При await во вторичных задачах(которые не основные) нас возвращает в основную задачу: в метод main(), на то же место и мы продолжаем читать, да?
Resurce InheiT Мастер (1089) Олег Дипникович, Верно. asyncio.create_task(one()) создает задачу для one() и планирует ее выполнение в event loop. Основная задача main() продолжает выполняться до await. При await в one() управление передается event loop-у, который смотрит, какие еще задачи готовы к выполнению. Как только one() завершит ожидание (например, завершится asyncio.sleep), event loop возобновит ее с того места, где она была приостановлена. Если в main() есть await, то она также приостанавливается, отдавая управление другим задачам. Когда все await в main() завершатся, она тоже закончит выполнение.
Senior Backend Developer Оракул (80918) 2 месяца назад
Если коротко event loop - это как шахматный гроссмейстер, который играет с несколькими игроками (корутинами) одновременно, логика точно такая же, await говорит ему, что он может переключиться на другую задачу пока выполняется эта. То есть гроссмейстер во время await сделал ход и передает ход игроку, как только игрок закончил свой ход он ждет пока гроссмейстер закончит свои текущие задачи и вернется к нему.
Олег ДипниковичПрофи (740) 2 месяца назад
как только игрок закончил свой ход он ждет пока гроссмейстер закончит свои текущие задачи и вернется к нему
То есть, допустим, запустился метод one(), поставился await, а затем event_loop переключился на задачу two(). И допустим, задача two() довольно трудоемкая. И когда время sleep у one() вышло, event_loop работает еще с two(). one() будет ждать, пока event_loop закончит очередь с two(), и только потом event_loop перейдет снова на one() да?
Олег Дипникович Профи (740) Олег Дипникович, то есть если у one() asyncio.sleep равен 1, то в данном случае продолжиться выполнение метода one() может не через 1 секунду, а через секунд 5
Похожие вопросы