Python asyncio.Task cancel()未加入事件循环时无法取消的问题
关于Python asyncio任务取消状态延迟生效的解释
这不是bug,是asyncio任务调度与取消机制的正常行为,具体原因如下:
任务创建后的状态
调用asyncio.create_task()创建任务时,任务会被加入事件循环的待调度队列,但此时事件循环并没有立刻处理这个任务——它需要等待当前协程让出执行权后,才会开始处理队列中的任务。cancel()的实际作用
调用t.cancel()只是给任务添加了一个取消请求标记,但这个标记不会直接修改任务的取消状态。任务只有在被事件循环调度执行、或者在等待可等待对象(比如asyncio.sleep)时,才会检测到取消请求并更新自身状态。await asyncio.sleep(0)的作用
这句代码的作用是主动让出执行权,让事件循环有机会处理待调度队列中的任务。当事件循环处理到你创建的t任务时,会检测到已存在的取消请求,随即把任务的状态更新为已取消,此时t.cancelled()就会返回True。为什么不能立刻看到取消状态
asyncio的取消是协作式的,任务不会被动地立刻响应取消请求,必须等到它进入事件循环的调度流程、或者在自身的暂停点(比如await操作)才能处理取消。刚创建的任务还没进入调度流程,所以取消状态不会立即生效。
如果你想在调用cancel()后立刻确认取消状态,可以通过触发事件循环的一轮调度来实现,await asyncio.sleep(0)就是最简便的方式。
验证代码
修改代码后即可得到你预期的输出:
import asyncio async def main(): t = asyncio.create_task(asyncio.sleep(5)) t.cancel() await asyncio.sleep(0) print(t.cancelled()) # 输出True print(t.cancelled()) # 输出True if __name__ == "__main__": asyncio.run(main())
内容的提问来源于stack exchange,提问作者winwin
相关产品推荐
相关产品推荐

