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

Python 3.6中使用async for实现HTTP请求同时执行的问题

如何用asyncio实现多个HTTP请求的并发执行?

你当前的代码之所以是串行执行,问题出在**async for的工作方式**上:它会逐个遍历异步生成器的每一次yield,并且每次都会等待当前迭代里的await操作完成后,才会进入下一次循环。所以你的ticker生成器每次只能跑一个循环,自然是顺序输出的。

要实现真正的并发,我们需要把每个请求(或者每个独立的异步任务)包装成asyncio.Task,让事件循环同时调度这些任务,而不是逐个等待。下面给你两种可行的实现方式:

方式一:直接创建任务并批量等待

这是最直观的写法,适合明确知道要创建多少个任务的场景:

import asyncio
# 这里替换成你实际的aiohttp请求逻辑
async def fetch_data(delay, task_id):
    print(f"启动任务 {task_id}")
    await asyncio.sleep(delay)  # 模拟HTTP请求耗时
    print(f"任务 {task_id} 执行完成")
    return f"任务 {task_id} 的返回结果"

async def main():
    # 创建3个并发任务,每个任务延迟1秒
    task_list = [
        asyncio.create_task(fetch_data(1, 0)),
        asyncio.create_task(fetch_data(1, 1)),
        asyncio.create_task(fetch_data(1, 2))
    ]
    # 等待所有任务完成,同时收集结果
    all_results = await asyncio.gather(*task_list)
    print("所有任务执行完毕,结果:", all_results)

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

这段代码的输出会是:

启动任务 0
启动任务 1
启动任务 2
任务 0 执行完成
任务 1 执行完成
任务 2 执行完成
所有任务执行完毕,结果: ['任务 0 的返回结果', '任务 1 的返回结果', '任务 2 的返回结果']

关键说明:

  • asyncio.create_task()会把异步函数立即加入事件循环调度,不需要等待await就会开始执行
  • asyncio.gather(*task_list)会阻塞直到所有任务完成,并且按顺序返回每个任务的结果

方式二:用异步生成器批量创建任务

如果你需要通过生成器来动态生成任务(比如从列表/数据库里读取请求参数),可以用异步生成器配合列表推导式来创建任务,再批量等待:

import asyncio

async def fetch_data(delay, task_id):
    print(f"启动任务 {task_id}")
    await asyncio.sleep(delay)
    print(f"任务 {task_id} 执行完成")
    return f"任务 {task_id} 的返回结果"

# 异步生成器,用来批量生成任务
async def generate_tasks(total_tasks, delay):
    for task_id in range(total_tasks):
        yield asyncio.create_task(fetch_data(delay, task_id))

async def main():
    # 从生成器里收集所有任务
    task_list = [task async for task in generate_tasks(3, 1)]
    # 等待所有任务完成
    all_results = await asyncio.gather(*task_list)
    print("所有任务执行完毕,结果:", all_results)

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

这种写法的效果和方式一完全一样,但更适合动态生成任务的场景。

核心要点总结

  • async for本身是串行迭代工具,它的作用是逐个处理异步生成器的输出,不是用来实现并发的
  • 实现并发的核心是创建多个独立的Task对象,让asyncio的事件循环同时调度它们
  • 用asyncio.gather()或asyncio.wait()来统一等待所有并发任务完成,避免遗漏任务状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:09:03