[英]aiohttp how to save a persistent ClientSession in a class?
我正在編寫一個使用 aiohttp 執行 http 請求的類。 根據文檔,我不應該為每個請求創建一個 ClientSession,所以我想重用同一個會話。
代碼:
class TestApi:
def __init__(self):
self.session = aiohttp.ClientSession()
# async defs methods from here
做的時候
TestApi()
我收到錯誤:未Unclosed client session
。
持久化ClientSession
對象的解決方案是什么?
TestApi()
的表達式TestApi()
創建一個TestApi
對象並立即將其丟棄。 aiohttp
抱怨會話從未關閉(通過async with
塊或顯式調用close()
離開async with
),但即使沒有警告,不將 API 對象分配給變量也是沒有意義的被實際使用。
要重用會話,您的代碼需要有權訪問會話或持有它的對象:
async def fetch(url):
async with aiohttp.request('GET', url) as resp:
resp.raise_for_status()
return await resp.read()
async def main():
url1_data, url2_data = asyncio.gather(
fetch('http://url1'), fetch('http://url2'))
url3_data, url4_data = asyncio.gather(
fetch('http://url3'), fetch('http://url4'))
一種選擇是添加一個session
參數來fetch
(和其他函數)並使用在main()
創建的會話一致地調用它。 更好的選擇是創建一個 API 類並將全局函數(如fetch
轉換為方法:
class Http:
async def __aenter__(self):
self._session = aiohttp.ClientSession()
return self
async def __aexit__(self, *err):
await self._session.close()
self._session = None
async def fetch(self, url):
async with self._session.get(url) as resp:
resp.raise_for_status()
return await resp.read()
main()
仍然可以作為函數存在,但它可以始終如一地使用持有會話的對象:
async def main():
async with Http() as http:
url1_data, url2_data = await asyncio.gather(
http.fetch('http://url1'), http.fetch('http://url2'))
url3_data, url4_data = await asyncio.gather(
http.fetch('http://url3'), http.fetch('http://url4'))
在上面的代碼中, async with
語句用於確保只要離開范圍就關閉會話。
實際上,我認為你的代碼沒有任何根本性的錯誤。
除了,當您的TestApi對象被銷毀時,可能在程序完成時,您需要調用close函數。 否則你會收到此警告。
(這是一個需要等待的協程: https : //docs.aiohttp.org/en/stable/client_reference.html )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.