Python HTTPX | RuntimeError:连接池已关闭,而 6 个 HTTP 请求/响应仍在进行中

Ton*_*ony 1 python asynchronous python-asyncio httpx

我在使用 HTTPX 模块时多次遇到此错误。我相信我知道这意味着什么,但我不知道如何解决。

在下面的示例中,我有一个异步函数 Gather_players(),它将 get 请求发送到我正在使用的 API,然后返回指定 NBA 球队的所有球员的列表。在 teamRoster() 内部,我使用 asyncio.run() 来启动 Gather_players() ,这就是产生此错误的行:RuntimeError: The connection pool was closed while 6 HTTP requests/responses were still in-flight

async def gather_players(list_of_urlCodes):

    async def get_json(client, link):
        response = await client.get(BASE_URL + link)

        return response.json()['league']['standard']['players']

    async with httpx.AsyncClient() as client:

        tasks = []
        for code in list_of_urlCodes:
            link = f'/prod/v1/2022/teams/{code}/roster.json'
            tasks.append(asyncio.create_task(get_json(client, link)))
        
        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 in list_of_personIds:
            personId = person['personId']

            #listOfPLayers is a list of every NBA player that I got 
            #from a previous get request
            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
Run Code Online (Sandbox Code Playgroud)

*注意:我的原始脚本中的 teamRoster() 函数实际上是一个类方法,我还在脚本的前面部分使用了与异步函数相同的技术来发送多个 get 请求。

Ton*_*ony 5

我终于找到了解决这个问题的方法。由于某种原因,上下文管理器:async with httpx.AsyncClient() as client无法正确关闭 AsyncClient。解决此问题的一个快速方法是使用以下命令手动关闭它:client.aclose()

前:

async with httpx.AsyncClient() as client:

    tasks = []
    for code in list_of_urlCodes:
        link = f'/prod/v1/2022/teams/{code}/roster.json'
        tasks.append(asyncio.create_task(get_json(client, link)))

    list_of_people = await asyncio.gather(*tasks)

    return list_of_people
Run Code Online (Sandbox Code Playgroud)

后:

client = httpx.AsyncClient()

tasks = []
for code in list_of_urlCodes:
    link = f'/prod/v1/2022/teams/{code}/roster.json'
    tasks.append(asyncio.create_task(get_json(client, link)))

list_of_people = await asyncio.gather(*tasks)
client.aclose()    

return list_of_people
Run Code Online (Sandbox Code Playgroud)