繁体   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