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

使用Python HTTPX遇RuntimeError:连接池关闭时仍有请求在处理

解决HTTPX异步请求出现RuntimeError: The connection pool was closed while X HTTP requests/responses were still in-flight的问题

问题原因

你的代码存在两个核心问题触发该错误:

  1. 提前用asyncio.create_task()创建任务,这些任务会脱离asyncio.gather()的直接管控。当某个任务抛出异常时,asyncio.gather()会立即终止并抛出异常,触发async with httpx.AsyncClient()的上下文退出、连接池关闭,但其他已创建的任务可能仍在运行,继续使用已关闭的连接池就会报错。
  2. 未处理单个请求的异常,单个请求失败会直接导致整个异步任务组崩溃,进而引发连接池提前关闭。

解决方案

  1. 直接传递协程给asyncio.gather():无需提前用asyncio.create_task()包装协程,asyncio.gather()会自动调度协程执行,确保所有请求都在AsyncClient的上下文内完成后才关闭连接池。
  2. 添加异常处理:在单个请求的协程中捕获异常,避免单个请求失败影响整个任务组;或者在asyncio.gather()中设置return_exceptions=True,将异常作为结果返回,待所有任务完成后统一处理。

修改后的代码示例

方式一:请求级异常处理

async def gather_players(list_of_urlCodes):

    async def get_json(client, link):
        try:
            response = await client.get(BASE_URL + link)
            response.raise_for_status()  # 捕获HTTP状态码异常(如404、500)
            return response.json()['league']['standard']['players']
        except Exception as e:
            print(f"请求失败: {link}, 错误: {str(e)}")
            return []  # 返回空列表或其他默认值,避免中断整个任务组

    async with httpx.AsyncClient() as client:
        # 直接传递协程对象,无需create_task
        tasks = [get_json(client, f'/prod/v1/2022/teams/{code}/roster.json') for code in list_of_urlCodes]
        list_of_people = await asyncio.gather(*tasks)
        
        return list_of_people

def teamRoster(list_of_urlCodes: list) -> list:
        list_of_personIds = asyncio.run(gather_players(list_of_urlCodes))

        finalResult = []
        for person_list in list_of_personIds:
            for person in person_list:
                personId = person['personId']
                for player in listOfPlayers:
                    if personId == player['personId']:
                        finalResult.append({
                            "playerName": f"{player['firstName']} {player['lastName']}",
                            "personId": player['personId'],
                            "jersey": player['jersey'],
                            "pos": player['pos'],
                            "heightMeters": player['heightMeters'],
                            "weightKilograms": player['weightKilograms'],
                            "dateOfBirthUTC": player['dateOfBirthUTC'],
                            "nbaDebutYear": player['nbaDebutYear'],
                            "country": player['country']
                        })

        return finalResult

方式二:统一处理异常(保留异常信息)

如果需要后续处理异常,可修改gather调用:

list_of_people = await asyncio.gather(*tasks, return_exceptions=True)

之后在结果处理阶段过滤或处理异常:

for result in list_of_people:
    if isinstance(result, Exception):
        # 自定义异常处理逻辑,如记录日志
        continue
    # 正常处理返回的球员数据

额外注意事项

如果你的类方法会被高频调用,反复使用asyncio.run()会不断创建销毁事件循环,影响性能。可以考虑将类的核心逻辑改为异步,复用事件循环,避免不必要的资源消耗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:01:55