python - aiohttp如何在一个类中保存一个持久化的ClientSession?

标签 python httprequest python-asyncio aiohttp

我正在编写一个将使用 aiohttp 执行 http 请求的类。根据文档,我不应该为每个请求创建一个 ClientSession,所以我想重用同一个 session 。

代码:

class TestApi:
   def __init__(self):
      self.session = aiohttp.ClientSession()

   # async defs methods from here 

做的时候

TestApi()

我收到错误:Unclosed client session

持久化 ClientSession 对象的解决方案是什么?

最佳答案

一行中的表达式 TestApi() 本身创建了一个 TestApi 对象并立即将其丢弃。 aiohttp 提示 session 从未关闭(通过保留 async with block 或显式调用 close()),但即使在没有警告的情况下,不将 API 对象分配给将实际使用它的变量是没有意义的。

要重用 session ,您的代码需要有权访问 session 或持有它的对象:

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() 中创建的 session 一致地调用它>。更好的选择是创建一个 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() 仍然可以作为函数存在,但它可以始终使用持有 session 的对象:

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 语句用于确保在离开作用域时关闭 session 。

关于python - aiohttp如何在一个类中保存一个持久化的ClientSession?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53496781/

相关文章:

java - Request.getParameter java 到 vb.net

带有 token 的python http请求

python - 多个 aiohttp Application() 在同一个进程中运行?

python - 如何使用 Ctrl+C 优雅地关闭协程?

python - 如何使用 MySQLdb 将整数和字符串值插入 MySQL?

python - 如何设置PyQt5 Qtimer以指定的时间间隔更新?

python - 使用另一个时间序列的索引对时间序列重新采样

使用spyder进行Python分析: times for constituents do not sum up to a total function's time

java - 在 Netty 中处理 Http 状态码 302 Moved Temporarily

python - 使用 @pytest.fixture(scope ="module") 和 @pytest.mark.asyncio