web-dev-qa-db-ja.com

Pythonパッケージ-aiohttpに「クライアントセッションが閉じられていません」という警告メッセージが表示される

私のコードは次のとおりです:

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()

コードを実行すると、警告メッセージが表示されます:nclosed client session

誰かが私にそれについていくつかの解決策を与えることができますか?

どうもありがとう

7
Zhe Xiao

最後に接続を閉じる必要があります。次の2つのオプションがあります。

手動で接続を閉じることができます:

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

または、contexマネージャで使用できます。

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))

クライアントセッションは、セルフクローズ用のコンテキストマネージャプロトコルをサポートしています。

12
Yuval Pruss

リソースを適切にブロック/解放するには、非同期コンテキストマネージャを使用してClientSessionを使用する必要があります。

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
2

コンテキストマネージャを使用していない場合は、適切に閉じる方法でもawaitが必要になります。ほとんどの人がより便利なコンテキストマネージャーを使用しているためと考えられ、インターネット上の多くの回答はその部分を見逃しており、実際にそれに気づく人はほとんどいません。ただし、unittestingを実行するときにawait session.close()内のクラス全体のセッションを閉じる場合、手動のtearDownClass()は不可欠です。

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