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

Python 3中如何让asyncio按顺序执行函数?实例解析

咱们先搞清楚为啥会出现乱序的情况,再看怎么解决~

为啥会出现无序输出?

核心原因就是多线程的并发调度特性:当你用ThreadPoolExecutor设置了多个工作线程时,提交的任务会被分配到不同线程中同时执行,而线程的执行顺序完全由操作系统的调度器决定。

哪怕你严格按0到9的顺序提交任务,不同线程的执行速度可能因为CPU时间片分配、系统负载等细微差异,导致后提交的任务反而先完成。比如线程池只有4个线程时,前4个任务(0-3)同时启动,当某个线程完成后会立刻取下一个任务(比如4),如果任务9所在的线程比任务8的线程更早结束,那9就会比8先被打印出来,自然就乱序了。

另外,如果你的代码是一次性把所有任务都扔给事件循环并发执行(比如用asyncio.create_task批量创建任务),而不是等前一个任务做完再提交下一个,这种并发执行的方式会让输出顺序的不确定性更明显。

怎么确保始终按0-9顺序输出?

这里有两种实用方案,你可以根据自己的需求选:

方案1:保留并发,统一按顺序输出

这种方法既保留了多线程并发执行的效率(所有任务同时跑,节省时间),又能保证输出顺序正确。思路是让任务只负责返回结果,不直接打印,等所有任务都完成后,再按提交顺序统一输出:

import asyncio
from concurrent.futures import ThreadPoolExecutor

async def get_task_result(num, pool):
    loop = asyncio.get_running_loop()
    # 线程池里执行任务,只返回结果不打印
    return await loop.run_in_executor(pool, lambda: num)

async def main():
    with ThreadPoolExecutor(max_workers=4) as executor:
        # 先把所有任务都提交,得到一组future对象
        task_futures = [get_task_result(i, executor) for i in range(10)]
        # 用asyncio.gather等待所有任务完成,它会严格按提交顺序返回结果
        results = await asyncio.gather(*task_futures)
        # 现在按顺序打印就行啦
        for num in results:
            print(num)

asyncio.run(main())

方案2:串行执行任务(逐个等待)

如果你不在乎并发的效率,只需要简单粗暴保证顺序,那可以改成等前一个任务完全完成后,再提交下一个任务:

import asyncio
from concurrent.futures import ThreadPoolExecutor

async def print_single_num(num, pool):
    loop = asyncio.get_running_loop()
    await loop.run_in_executor(pool, print, num)

async def main():
    with ThreadPoolExecutor(max_workers=4) as executor:
        # 一个一个来,等当前任务打印完再搞下一个
        for i in range(10):
            await print_single_num(i, executor)

asyncio.run(main())

这种方式下,每个任务必须等前一个任务打印结束才会启动,所以输出顺序肯定是0到9,但缺点是多线程的并发优势就没了,任务相当于串行执行,速度会慢一些。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:32:21