使用async with仍出现aiohttp未关闭客户端会话错误的排查
问题原因及解决方法
你的问题出在ClientSession没有被上下文管理器正确管理。
看你do函数里的这段代码:
async with aiohttp.ClientSession().request(method, url, **args) as res:
这里的async with只接管了request()返回的响应对象(res),而你创建的ClientSession对象完全没被上下文管理器包裹。请求结束后,响应会被关闭,但会话本身还在内存里没被正确关闭,所以才会弹出未关闭会话的警告。
修复方法
把ClientSession也放进async with里,让上下文管理器同时管理会话和请求:
修改后的do函数代码:
async def do(method, path, req=None, auth=False): args = {} params = None if req: try: params = json.loads(json.dumps(req)) except Exception: params = None if params: args = dict(params=params) url = make_url(path, params) if auth: args['auth'] = aiohttp.BasicAuth(lapikey, lapisecret) # 先把ClientSession放进async with,再在里面发起请求 async with aiohttp.ClientSession() as session: async with session.request(method, url, **args) as res: try: return await res.json() except Exception as e: return e
额外优化建议
如果你的代码需要发起多次请求,最好把ClientSession的创建提到上层(比如get_all_balances或者主函数里),复用同一个会话,这样能减少连接开销,效率更高。比如:
async def get_all_balances(): async with aiohttp.ClientSession() as session: return await do(session, 'GET', '/api/1/balance', auth=True) # 同时修改do函数,接收session参数 async def do(session, method, path, req=None, auth=False): args = {} params = None if req: try: params = json.loads(json.dumps(req)) except Exception: params = None if params: args = dict(params=params) url = make_url(path, params) if auth: args['auth'] = aiohttp.BasicAuth(lapikey, lapisecret) async with session.request(method, url, **args) as res: try: return await res.json() except Exception as e: return e
这样不仅解决了会话未关闭的问题,还能提升请求效率。
内容的提问来源于stack exchange,提问作者wil
相关产品推荐
相关产品推荐

