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

asyncio.as_completed()异常:生成器仅返回首个元素的解决方法

解决异步生成器仅返回首个元素的问题

看起来你的代码里有几个关键问题导致了这个现象,咱们一步步排查并修复:

1. 重复创建ClientSession的隐患

你的fetch函数每次调用都会新建一个aiohttp.ClientSession,这不仅会浪费连接资源,还可能导致请求阻塞或意外中断。正确的做法是在整个程序生命周期内复用同一个Session。

2. 未处理协程异常

如果某个分页请求抛出异常(比如网络错误、API返回格式异常),await routine会直接抛出未捕获的异常,导致异步生成器提前终止,只返回之前已经yield的结果。必须给每个协程添加异常捕获逻辑。

3. 分页逻辑的小问题

你的paginate函数用offset <= size,但如果total是总条目数,当offset等于total时,请求的分页数据会是空的(没有可返回的条目),虽然这不会直接导致生成器停止,但会产生无意义的空结果,建议改成offset < total。

修正后的完整代码

import asyncio
import aiohttp

async def fetch(session, url, params=None):
    try:
        async with session.get(url, params=params) as response:
            response.raise_for_status()  # 捕获4xx/5xx等HTTP错误状态码
            return await response.json()
    except Exception as e:
        print(f"请求失败: {e}")
        return None  # 或根据业务需求返回默认值

async def get_all_pages(session, base_url):
    def paginate(total_items):
        limit = 100
        offset = 0
        # 修正分页条件:避免请求空数据页
        while offset < total_items:
            yield {"offset": offset, "limit": limit}
            offset += limit

    # 先获取总条目数,同时处理请求失败的情况
    initial_response = await fetch(session, base_url)
    if not initial_response:
        return
    total = initial_response["data"]["total"]
    coroutines = [fetch(session, base_url, params) for params in paginate(total)]
    print(f"总条目数: {total}, 协程总数: {len(coroutines)}")

    # 遍历所有完成的协程,确保单个协程失败不影响整体
    for future in asyncio.as_completed(coroutines):
        r = await future
        # 校验返回数据格式,避免格式异常中断生成器
        if r and "data" in r and "field" in r["data"]:
            yield r["data"]["field"]

async def main():
    url = "http://arandomurl.com"
    # 全局复用一个ClientSession,提升请求效率
    async with aiohttp.ClientSession() as session:
        results = []
        async for x in get_all_pages(session, url):
            results.append(x)
        print(f"获取到的结果数量: {len(results)}")

asyncio.run(main())

关键修改说明

  • 复用Session: 在main中创建唯一的ClientSession并传递给其他函数,避免重复创建Session带来的资源浪费和连接问题。
  • 全链路异常处理: 在fetch中捕获所有请求相关异常,同时校验返回数据格式,确保单个请求失败不会导致整个生成器终止。
  • 优化分页逻辑: 修正分页条件,避免请求无数据的空分页。

这样修改后,异步生成器就能正确返回所有分页的结果,而不是仅返回第一个元素了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 10:27:35