asyncio
сопрограммы не выполняются сами по себе, они выполняются циклом событий .
Цикл событий получает управление на asyncio.run
и начинает выполнять некоторую сопрограмму.Когда поток выполнения достигает чего-то блокирующего, например await asyncio.sleep()
или await future
, он возвращает управление обратно в цикл обработки событий.Это позволяет циклу событий запускать или возобновлять выполнение чего-то еще.
Посмотрите на пример и рисунок здесь , чтобы увидеть его на простом примере.
In пример о cancel()
происходит следующее:
await asyncio.sleep(0)
, а также 1
вернет управление в цикл событий - Цикл событий начнетexecute
cancel_me()
cancel_me()
в итоге наткнется на что-то блокирующее и вернет управление обратно в цикл событий - Цикл событий возобновит выполнение
main()
main()
пометит задачу, которая будет отменена, с помощью task.cancel()
и ждет ее отмены с помощью await task
Если у вас, однако, нет asyncio.sleep()
на первом этапе, поток выполнения даже не достигнет cancel_me()
потому что цикл обработки событий никогда не получал контроль между созданием и отменой задачи.Когда цикл обработки достигает значения await task
, он видит, что задача никогда не запускалась, и помечает для отмены: нет смысла запускать ее сейчас.