I want to create a persistent session that last until the program ends, I have the following code.
import asyncio
import aiohttp
import atexit
class Session:
def __init__(self):
self._session = aiohttp.ClientSession()
atexit.register(self._close_session)
async def get(self, url):
response = await self._session.request("GET", url)
return await response.json()
def _close_session(self):
asyncio.run(self._session.close())
async def pullit():
print(await session.get("https://raw.communitydragon.org/latest/game/data/characters/aatrox/aatrox.bin.json"))
session = Session()
asyncio.run(pullit()) # THIS THROWS: Timeout context manager should be used inside a task
asyncio.get_event_loop().run_until_complete(pullit()) #THIS RUNS OK
This throws me an exception on the self._session.request line with Timeout context manager should be used inside a task, I've searched for other answers but it is still giving the same error.
Question: What is the cause of this error? If I want to open a session that last the lifetime of a program, and I need it to be defined inside a class (obligatory), how would that be ?
Extra: Currently I am using atexit to close the session when the program ends (refer above code), is this a good way of doing so ? if not, what is a better practice
UPDATE: I found the solution to this, it was to use asyncio.get_event_loop().run_until_complete(...), but isn't asyncio.run() the same as above ? why does one runs without problem and the 3.7+ asyncio.run() doesn't run ?
UPDATE 2: I ended up with the following code:
#runner.py
import aiohttp
import asyncio
class Runner:
def __init__(self, coro):
self.coro = coro
async def run(self):
session = aiohttp.ClientSession()
client.start_session(session)
await self.coro
client.close_session()
await session.close()
def run(coro):
runner = Runner(coro)
return asyncio.run(runner.run())
#client.py
class Client:
def __init__(self):
self._session = None
async def get(self, url):
response = await self._session.request("GET", url)
return await response.json()
def start_session(self, session):
self._session = session
def close_session(self):
self._session = None
from .runner import run
from .client import Client
client = Client()
async def pullit():
print(await client.get("https://raw.communitydragon.org/latest/game/data/characters/aatrox/aatrox.bin.json"))
run(pullit())
OK, this runs and everything but after it runs it throws me RuntimeError: Event loop is closed, which I never closed a loop.