学習演習として、aiohttpのクイックスタートの例を変更して、単一のClientSessionで複数のURLをフェッチしようとしています(ドキュメントでは、通常、アプリケーションごとに1つのClientSessionを作成する必要があるとされています)。
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main(url, session):
print(f"Starting '{url}'")
html = await fetch(session, url)
print(f"'{url}' done")
urls = (
"https://python.org",
"https://Twitter.com",
"https://tumblr.com",
"https://example.com",
"https://github.com",
)
loop = asyncio.get_event_loop()
session = aiohttp.ClientSession()
loop.run_until_complete(asyncio.gather(
*(loop.create_task(main(url, session)) for url in urls)
))
# session.close() <- this doesn't make a difference
ただし、コルーチンの外部でClientSessionを作成することは、明らかにその方法ではありません。
➜python 1_async.py 1_async.py:30:UserWarning:コルーチンの外部でクライアントセッションを作成することは非常に危険なアイデアです session = aiohttp.ClientSession() コルーチン外でのクライアントセッションの作成 client_session: 開始 'https://python.org' 開始 'https://Twitter.com' 開始 'https://tumblr.com' 開始 'https://example.com' 開始 'https:/ /github.com' 'https://Twitter.com'done 'https://example.com'done 'https://github.com'done 'https://python.org' done 'https://tumblr.com' done 1_async.py:34:RuntimeWarning:coroutine'ClientSession.close 'was待たない session.close() 閉じられていないクライアントセッション client_session: 閉じられていないコネクタ 接続:['[(、15024.110107067)]' 、 '[(、15024.147785039)]'、 '[(、15024.252375415)]'、 '[(、15024.292646968)]'、 '[(、15024.342368087)]'、 '[(、15024.466971983)]'、 '[(、 150 24.602057745)] '、' [(、15024.837045568)] '] コネクタ:
FWIW、上記の変更を試みる前はmain
でした。
async def main(url):
async with aiohttp.ClientSession() as session:
print(f"Starting '{url}'")
html = await fetch(session, url)
print(f"'{url}' done")
これを行う正しい方法は何でしょうか? URLのリストをmainに渡すことを考えましたが、非順次的に機能させることができませんでした。
_Creating a client session outside of coroutine is a very dangerous idea
_は、作成時に現在のループにバインドされるためです。後で実行ループを変更すると、ハングします。しかし、十分注意深く使用すれば、無視することができます。 関連ドキュメント 。
私に関しては、私はこの警告を無視するだけです。しかし、それを克服することも簡単です。
_async def create_session():
return aiohttp.ClientSession()
session = asyncio.get_event_loop().run_until_complete(create_session())
_
さらに、Task
オブジェクトを明示的に作成する必要はありませんが、次のコルーチン関数を実行するだけです。
_loop.run_until_complete(asyncio.gather(
*(main(url, session) for url in urls)
))
_
最後に、close
がコルーチンであることを忘れないでください。 loop.run_until_complete(session.close())
を使用してsession
を閉じる必要があります。
ところで、非同期のようなループを作成したい場合は、 私の別の答え を参照できます。