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

如何使用async/await加速请求处理同时保留原始数据ID顺序?

问题

我想用async模拟向网站发送请求并等待返回结果,要求按原始ID顺序输出结果而非异步执行后的乱序。当前代码如下:

import asyncio
import random

class Count: #Assume data only hold the data ID number
  count = 0

def output(count):
  print(count) #Assume storing the ID and content of the website into a database

async def count():
  while True:
    Count.count = Count.count + 1 #Update the data reference ID by increasing one
    count = Count.count #Assume ID is the variable that will be pass to a website
    await asyncio.sleep(random.randint(1, 10)) #Simluate connect to the website and passing the ID variables and return the result from the website
    output(count)
    if Count.count>9:
      break

async def main():
  await asyncio.gather(count(), count(),count(),count())
if __name__ == "__main__":
  asyncio.run(main())

执行结果为:

3
1
5
4
2
6
8
7
10
9

该结果不符合预期,虽然async/await提升了处理速度,但牺牲了数据顺序。我希望在保留异步加速的同时,维持ID从1到10的输出顺序。我可以先保存所有数据再按ID排序,但有没有更优的方式,比如让第二个异步count()协程的output()调用在第一个的output()完成后再执行?预期输出为:

1
2
3
4
5
6
7
8
9
10

解决方案

要实现异步请求+按ID顺序输出,无需等待所有请求完成再排序,也不用让协程输出互相阻塞,可通过拆分"请求任务"与"输出逻辑"的方式实现,兼顾性能与顺序要求。

方案一:基于gather的有序结果返回

利用asyncio.gather的特性——它会严格按照传入任务列表的顺序返回结果,即使部分请求先完成,最终结果列表仍保持原任务顺序。

import asyncio
import random

def output(count):
    print(count)  # 模拟将ID和内容存入数据库

async def fetch_data(id_num):
    # 模拟网站请求的随机耗时
    await asyncio.sleep(random.randint(1, 10))
    return id_num

async def main():
    # 生成1到10的请求任务列表
    tasks = [fetch_data(i) for i in range(1, 11)]
    # 异步执行所有任务,按原顺序获取结果
    results = await asyncio.gather(*tasks)
    # 按ID顺序输出结果
    for res in results:
        output(res)

if __name__ == "__main__":
    asyncio.run(main())

方案二:基于队列的实时有序输出

如果不想等待所有请求完成再输出,而是希望前面的ID请求完成后立刻输出,可借助异步队列实现:单独启动一个协程按顺序消费队列,所有请求完成后将结果放入队列,确保输出顺序。

import asyncio
import random

async def ordered_output(queue):
    # 按ID顺序从队列取结果输出
    for _ in range(1, 11):
        res = await queue.get()
        print(res)
        queue.task_done()

async def fetch_data(id_num, queue):
    # 模拟网站请求耗时
    await asyncio.sleep(random.randint(1, 10))
    # 请求完成后将结果放入队列
    await queue.put(id_num)

async def main():
    queue = asyncio.Queue()
    # 启动有序输出协程
    output_task = asyncio.create_task(ordered_output(queue))
    # 启动所有请求协程
    fetch_tasks = [fetch_data(i, queue) for i in range(1, 11)]
    await asyncio.gather(*fetch_tasks)
    await queue.join()
    output_task.cancel()

if __name__ == "__main__":
    asyncio.run(main())

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:25:43