aiohttp 如何在 class 中保存一个持久化的 ClientSession?
aiohttp how to save a persistent ClientSession in a class?
我正在编写一个 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
对象并立即将其丢弃。 aiohttp
抱怨会话从未关闭(通过留下 async with
块或显式调用 close()
),但即使没有警告,不分配也没有意义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 class 并将 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
语句用于确保在离开范围时关闭会话。
我正在编写一个 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
对象并立即将其丢弃。 aiohttp
抱怨会话从未关闭(通过留下 async with
块或显式调用 close()
),但即使没有警告,不分配也没有意义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 class 并将 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
语句用于确保在离开范围时关闭会话。