簡體   English   中英

aiohttp 如何在類中保存持久的 ClientSession?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM