Python HTTPX | RuntimeError: The connection pool was closed while 6 HTTP requests/responses were still in-flight

Question:

I’ve come across this error multiple times while using the HTTPX module. I believe I know what it means but I don’t know how to solve it.

In the following example, I have an asynchronous function gather_players() that sends get requests to an API I’m using and then returns a list of all the players from a specified NBA team. Inside of teamRoster() I’m using asyncio.run() to initiate gather_players() and that’s the line that produces this error: 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

*Note: The teamRoster() function in my original script is actually a class method and I’ve also used the same technique with the asynchronous function to send multiple get request in an earlier part of my script.

Asked By: Tony

||

Answers:

I was able to finally find a solution to this problem. For some reason the context manager: async with httpx.AsyncClient() as client fails to properly close the AsyncClient. A quick fix to this problem is closing it manually using: client.aclose()

Before:

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

After:

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
Answered By: Tony