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

asyncio.create_task实际工作机制解析:基于示例代码的技术疑问

理解asyncio.create_task的工作机制

第一段代码(耗时约2秒)

import asyncio
import time

async def delayer():
    await asyncio.sleep(1)

async def messenger():
    await asyncio.sleep(1)
    return "A Message"

async def main():
    message = await messenger()
    await delayer()

start_time = time.time()

asyncio.run(main())

end_time = time.time() - start_time

print(end_time)

这段代码里,await messenger()会阻塞当前main协程,必须等messenger内部的asyncio.sleep(1)执行完、拿到返回值后,才会继续执行await delayer()。两个1秒的等待是串行执行的,所以总耗时约2秒。

第二段代码(耗时约1秒)

import asyncio
import time

async def delayer():
    await asyncio.sleep(1)

async def messenger():
    await asyncio.sleep(1)
    return "A Message"

async def main():
    task1 = asyncio.create_task(delayer())
    task2 = asyncio.create_task(delayer())

    await task1
    await task2

start_time = time.time()

asyncio.run(main())

end_time = time.time() - start_time

print(end_time)

这段代码总耗时仅约1秒,核心差异就在asyncio.create_task的使用逻辑上。


核心疑问解答

你疑惑的“既然await需要等待返回,用了create_task为什么不会总耗时2秒”,可以拆解成两个关键逻辑:

  1. create_task的即时调度特性:调用asyncio.create_task(delayer())时,会立刻把delayer协程包装成任务对象,提交给asyncio事件循环,事件循环会尽快启动这个任务的执行——也就是说,task1和task2对应的delayer代码,在你调用create_task之后就已经开始运行了,不是等你await的时候才启动。
  2. await对任务对象的非独占阻塞:当你await task1时,确实会暂停当前的main协程,但事件循环不会闲着,它会立刻去调度其他已经就绪的任务(比如task2)。在这个示例里,两个delayer内部的asyncio.sleep(1)是同时开始计时的,1秒后两个sleep都完成,后续的await task1和await task2都会快速结束,所以总耗时约1秒。

结合你已掌握的知识点补充:

  • await是“协程内阻塞”而非“进程阻塞”:await只会暂停当前所在的协程,整个进程不会卡住,事件循环会去处理其他可运行的任务/协程。
  • create_task的本质是“并行预约”:它把协程变成可被事件循环调度的独立任务,相当于提前给协程排了号,让事件循环能在当前协程暂停时,去执行这些预约好的任务。

对比第一段代码就能更清楚:第一段里只有messenger一个协程在等待,事件循环无事可做只能等它完成;而第二段通过create_task提前提交了两个任务,当第一个await暂停main时,事件循环可以去跑第二个任务,让两个sleep并行执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:55:21