【问题标题】:Why we need the `Asyncio.sleep` to start the loop?为什么我们需要 `Asyncio.sleep` 来启动循环?
【发布时间】:2019-08-21 14:26:46
【问题描述】:
在这个document of Asyncio中,我们可以看到它使用await asyncio.sleep(1)延迟1秒然后取消任务。
我尝试将其更改为await asyncio.sleep(0),它也很好用。
但是当我尝试删除await asyncio.sleep(1) 时,程序似乎不会进入函数cancel_me。所以它只是出现在 cli 中的main(): cancel_me is cancelled now。
这是什么原因?
【问题讨论】:
标签:
python-3.x
python-asyncio
【解决方案1】:
asyncio 协程不是自己执行的,而是由event loop 执行的。
事件循环接收asyncio.run 的控制权并开始执行一些协程。当执行流到达像await asyncio.sleep() 或await future 这样的阻塞时,它会将控制权返回给事件循环。它允许事件循环开始或恢复执行其他东西。
看示例和图片here 以查看简单示例。
在example关于cancel()下面发生:
-
await asyncio.sleep(0) 和 1 会将控制权返回给事件循环
- 事件循环将开始执行
cancel_me()
-
cancel_me() 最终会偶然发现一些阻塞并将控制权返回给事件循环
- 事件循环将继续执行
main()
-
main() 将使用task.cancel() 标记要取消的任务,并使用await task 等待它取消
如果您在第一步中没有asyncio.sleep(),则执行流程甚至不会到达cancel_me(),因为事件循环从未获得任务创建和任务取消之间的控制权。当事件循环到达await task 时,它会看到任务从未启动并标记为取消:现在启动它没有意义。