You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

asyncio.create_task未await结果与gather执行差异及异常原因问询

asyncio 相关问题解答

问题1:create_task 与 gather 的执行差异及 gather 抛异常的原因

核心触发点是你的代码中 asyncio.gather 调用前没有加await,具体逻辑拆解如下:

  • create_task 调用后,对应任务会被立刻提交到当前事件循环的调度队列,只要事件循环正常运行就会被分配时间片执行。你开头创建的3个create_task任务执行到await asyncio.sleep(1)时会让出CPU,事件循环随即调度后续代码逻辑。
  • asyncio.gather 本身是协程函数,接收的参数如果是原生协程对象,会自动把协程包装成Task提交到事件循环调度,所以你又生成了3个新的sleep_and_print任务——这就是输出中有6条「开始执行」日志的原因:3条来自开头的create_task,3条来自gather自动包装的任务。
  • 抛出CancelledError的原因:你没有await gather协程,main函数在创建完gather对应的协程对象后直接执行结束,asyncio.run(main())会在main返回后自动关停事件循环,关停前会取消所有未完成的运行中任务,包括前面创建的3个Task、gather自动创建的3个Task,以及gather本身的Future对象,未被捕获的取消事件就抛出了对应异常,所有任务都卡在await asyncio.sleep(1)的位置,没机会执行后续的完成打印。

如果你将gather调用改为await asyncio.gather(*[sleep_and_print(i) for i in range(3)]),main会等待gather的所有任务执行完毕才返回,1秒的等待时间足够所有6个任务执行完成,不会再抛出取消异常。


问题2:仅 await 第二个任务时两个任务都能执行完成的原因

  • await asyncio.create_task(sleep_and_print(1))会阻塞当前的main协程,直到第二个任务完全执行完毕才会继续向下执行,整个阻塞时长为1秒。
  • 这1秒的等待窗口内,事件循环是正常运行的,此前创建的第一个任务asyncio.create_task(sleep_and_print(0))会被正常调度,sleep(1)结束后就会执行完成打印,和第二个任务几乎同时执行完毕,所以两个任务都能跑完。
  • 对比你最初的代码,main没有任何等待逻辑,创建完所有任务后立刻返回,事件循环直接关停,所有还在等待sleep结束的任务都被直接取消,因此只有开始执行的日志,没有完成日志。

内容的提问来源于stack exchange,提问作者anjuna47

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 08:48:02