Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python package - aiohttp has a warning message "Unclosed client session"

My code is as follows:

import asyncio
import aiohttp

urls = [
    'http://www.163.com/',
    'http://www.sina.com.cn/',
    'https://www.hupu.com/',
    'http://www.csdn.net/'
]

async def get_url_data(u):
    """
    read url data
    :param u:
    :return:
    """
    print('running ', u)
    resp = await aiohttp.ClientSession().get(url=u)
    headers = resp.headers
    print(u, headers)
    return headers


async def request_url(u):
    """
    main func
    :param u:
    :return:
    """
    res = await get_url_data(u)
    return res

loop = asyncio.get_event_loop()
task_lists = asyncio.wait([request_url(u) for u in urls])
loop.run_until_complete(task_lists)
loop.close()

When i running my code, it's display a warning message: Unclosed client session

Anybody can give me some solutions about that?

Thanks a lot

like image 425
Zhe Xiao Avatar asked Sep 08 '17 09:09

Zhe Xiao


3 Answers

You should close the connection in the end. You have 2 options:

You can close the connection manually:

import aiohttp
session = aiohttp.ClientSession()
# use the session here
session.close()

Or you can use it with a contex manager:

import aiohttp
import asyncio

async def fetch(client):
    async with client.get('http://python.org') as resp:
        assert resp.status == 200
        return await resp.text()

async def main(loop):
    async with aiohttp.ClientSession(loop=loop) as client:
        html = await fetch(client)
        print(html)

loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))

The client session supports the context manager protocol for self closing.

like image 77
Yuval Pruss Avatar answered Oct 11 '22 10:10

Yuval Pruss


If you are not using context manager, the proper way to close it would also need an await. Many answers on the internet miss that part, and few people actually notice it, presumably because most people use the more convenient context manager. But the manual await session.close() is essential when/if you are closing a class-wide session inside the tearDownClass() when doing unittesting.

import aiohttp
session = aiohttp.ClientSession()
# use the session here
await session.close()
like image 36
RayLuo Avatar answered Oct 11 '22 10:10

RayLuo


You should use ClientSession using async context manager for proper blocking/freeing resources:

async def get_url_data(u):
    """
    read url data
    :param u:
    :return:
    """
    print('running ', u)
    async with aiohttp.ClientSession() as session:
        resp = await session.get(url=u)
        headers = resp.headers
        print(u, headers)
        return headers
like image 4
Mikhail Gerasimov Avatar answered Oct 11 '22 12:10

Mikhail Gerasimov