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

Python 3.7中async/await异步任务执行顺序异常问题咨询

嘿,这个问题我之前也碰到过,核心原因是你在异步任务里用了同步阻塞的time.sleep(2),把整个asyncio事件循环给完全卡住了!

问题根源拆解

asyncio的事件循环是单线程调度的,所有异步任务都在这同一个线程里运行。如果某个任务执行了像time.sleep这种同步阻塞的代码,事件循环会被彻底占用,根本没机会切换到其他任务,直到这个阻塞操作结束。所以你创建的三个second()任务会依次跑完它们的sleep,全部完成后才轮到first()任务执行,这就是为什么输出是SECOND SECOND SECOND先出来。

解决方法1:用异步版等待——asyncio.sleep()

把time.sleep(2)替换成await asyncio.sleep(2),这是asyncio专门提供的异步等待方法。它会主动把控制权交还给事件循环,让其他可运行的任务有机会执行。

修改后的完整代码:

import asyncio

async def first():
    print('FIRST')

async def second():
    await asyncio.sleep(2)  # 替换为异步sleep
    print('SECOND')

async def main():
    # 创建所有任务并加入事件循环队列
    tasks = [
        asyncio.create_task(second()),
        asyncio.create_task(second()),
        asyncio.create_task(second()),
        asyncio.create_task(first()),
        asyncio.create_task(first()),
        asyncio.create_task(first()),
    ]
    # 等待所有任务执行完成
    await asyncio.gather(*tasks)

asyncio.run(main())

运行这段代码,你会先看到FIRST FIRST FIRST立即输出,等待2秒后,SECOND SECOND SECOND才会打印出来——完全符合你的预期!

解决方法2:如果必须用同步阻塞函数

如果你的场景里必须使用像time.sleep这样的同步阻塞操作(比如某些第三方库没有异步版本),可以用asyncio.to_thread()把它放到单独的线程里执行,这样就不会阻塞事件循环:

import asyncio
import time

async def second():
    await asyncio.to_thread(time.sleep, 2)  # 把同步操作放到线程池
    print('SECOND')

这个方法会把同步函数交给线程池处理,事件循环可以继续调度其他任务,效果和用asyncio.sleep()一致。

额外补充:关于create_task的调度逻辑

create_task只是把协程包装成任务并加入事件循环的任务队列,但任务的执行完全依赖事件循环的调度。只有当当前任务主动释放控制权(比如遇到await),事件循环才会去调度队列里的其他任务。如果任务里全是同步阻塞代码,事件循环根本没机会切换,自然就会“等待”这个任务完成才处理下一个。

内容的提问来源于stack exchange,提问作者Mr.D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 14:23:13