I'm writing a CLI for accessing REST API. I have defined aiohttp.ClientSession
class field _client_session
in async init method.
How do I close the aiohttp.ClientSession
properly? If I do:
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()
I get this:
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>
I understand this happens for a reason: I close the loop
before garbage collector deletes profile
. The solution is to delete it manually with del
, but I don't want to do this.
It there a way to register the future for execution just before event loop closing?
asyncio
doesn't support IO in destructors.
The same for constructors and properties.
The recommended way is adding async with Profile
or await profile.close()
support.