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

Python中所有async/await表达式都具备异步性吗?

关于asyncio非阻塞性与串行await的疑问解答

为什么片段2和同步代码表现一致?

片段2中,await one()会直接暂停main协程,直到one()完全执行完毕才会继续执行await two()。也就是说,one()在sleep 3秒的过程中,事件循环里只有one这一个正在运行的任务,没有其他可调度的协程,只能等着one结束后再启动two。这种串行等待的逻辑和同步代码里先调用one()再调用two()完全一致,所以耗时和输出顺序自然没有区别。

asyncio的非阻塞性怎么体现?

asyncio的非阻塞不是“用了async/await就自动生效”,核心在于事件循环的调度逻辑:当一个协程遇到可等待的IO操作(比如asyncio.sleep、异步网络请求)时,它会主动把控制权交还给事件循环,此时事件循环可以去执行其他已经被调度好的协程(比如用create_task创建的任务)。

比如片段1里,asyncio.create_task(two())把two()包装成任务立刻提交给事件循环。当one()执行到await asyncio.sleep(3)时,它让出控制权,事件循环就会去运行two()任务,所以two()先完成输出,等3秒后one()再继续执行。

如果要让片段2体现非阻塞,只需要把两个协程并发调度,比如用asyncio.gather:

async def main():
    # 同时调度one和two,等待两者完成
    await asyncio.gather(one(), two())

asyncio.run(main())

这个版本的输出会是:

two done
one done

总耗时约3秒(而非同步的3.1秒),因为one()和two()的sleep操作是并行进行的,这就是非阻塞性的直观体现。

不使用create_task、run_in_executor时,asyncio还有优势吗?

有,但要结合场景来看:

  • 异步IO库适配:如果代码依赖异步IO驱动(比如aiohttp、asyncpg),即使是顺序await,也比同步代码高效。同步IO会阻塞整个线程,而asyncio的await只是让出控制权,事件循环可以在等待IO的间隙处理其他后台任务(比如定时器、信号处理)。
  • 代码扩展性:用async/await编写的代码,后续如果需要改成并发,只需要调整调度方式(比如添加create_task或gather);而同步代码要改成并发则需要重构为线程/进程模型,改动成本更高。
  • 单线程高IO场景:处理大量IO-bound任务时,asyncio的单线程模型比线程池开销更小——因为没有线程切换的额外成本,但前提是要把这些任务并发调度起来。

当然,如果只是像片段2那样,顺序执行两个无实际IO的协程(或纯sleep),那确实和同步代码没有区别,因为事件循环没有机会调度其他任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 07:28:15