【问题标题】:Closing aiohttp.ClientSession on parent object destruction在父对象销毁时关闭 aiohttp.ClientSession
【发布时间】:2019-03-03 03:32:27
【问题描述】:

我正在编写一个用于访问 REST API 的 CLI。我在异步初始化方法中定义了aiohttp.ClientSession类字段_client_session。

如何正确关闭aiohttp.ClientSession?如果我这样做:

import asyncio
import aiohttp


class Profile:                                                                    
    def __init__(self, loop):                                                     
        self._loop = loop                                                         
        self._client_session = None                                               

    def __del__(self):                                                            
        self._loop.run_until_complete(self._client_session.close())              

    async def async_init(self):
        self._client_session = aiohttp.ClientSession()                           

    @classmethod
    async def create(cls, loop):
        self = cls(loop)
        await self.async_init()
        return self


loop = asyncio.get_event_loop()
profile = loop.run_until_complete(Profile.create(loop))                          
loop.close()

我明白了:

Exception ignored in: <bound method Profile.__del__ of <profile.Profile object at 0x7f8ab82e15c0>>
Traceback (most recent call last):
File "/home/rominf/projects/profile/profile/__init__.py", line 197, in __del__
File "/home/rominf/.pyenv/versions/3.6.6/lib/python3.6/asyncio/base_events.py", line 444, in run_until_complete
File "/home/rominf/.pyenv/versions/3.6.6/lib/python3.6/asyncio/base_events.py", line 358, in _check_closed
RuntimeError: Event loop is closed
sys:1: RuntimeWarning: coroutine 'ClientSession.close' was never awaited
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7f8ab43bf588>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x7f8ab28a06a8>, 11519.944147989)]']
connector: <aiohttp.connector.TCPConnector object at 0x7f8ab43bf3c8>

我知道发生这种情况是有原因的:我在垃圾收集器删除 profile 之前关闭了 loop。解决办法是用del手动删除,但我不想这样做。

有没有办法在事件循环关闭之前注册未来执行?

【问题讨论】:

  • __aenter__/__aexit__ 方法呢?
  • @AzatIbrakov, __aexit__ 用于异步上下文管理器,它不用于对象销毁。我仍然收到:“未关闭的客户端会话”错误。
  • 好吧,您的事件循环似乎在关闭ClientSession 之前就已关闭,您能向我们展示更多您的代码吗?
  • @AzatIbrakov,我更新了问题。

标签: python python-3.x destructor python-asyncio aiohttp


【解决方案1】:

asyncio 不支持析构函数中的 IO。 构造函数和属性也是如此。

推荐的方法是添加async with Profile 或await profile.close() 支持。

【讨论】:

  • 感谢您的建议。我不想为Profile 实现上下文管理器,因为我将在代码的各个部分执行Profile 方法。我最终写了异步Profile.close。
  • 不同的用例需要不同的解决方案。这就是aiohttp.ClientSession 同时支持异步上下文管理器和异步关闭方法的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
  • 1970-01-01
  • 2014-11-24
  • 2013-11-28
相关资源
最近更新 更多