Reputation: 2628
I'm trying to write a discord bot that updates users with data I fetch from a http rest call.
Since discord.py uses asyncio, I thought I'd try following this approach through.
async def my_background_task():
print("starting BG task")
await client.wait_until_ready()
while not client.is_closed:
requests.get(getMyUrl()).json()["dict_element"]
#do more stuff
client.loop.create_task(my_background_task())
client.run("api key goes here")
It's straight forward enough using the sync "request" library. However I can run this for about a few hours until it crashes. I assume because of 'request' failing to finish the endless loop.
async def fetch(session, url):
async with session.get(url) as resp:
print(resp.status)
return await resp
async def fetch_url(loop, url):
async with aiohttp.ClientSession(loop=loop) as session:
await fetch(session, url)
async def my_method(url):
loop = asyncio.get_event_loop()
return loop.run_until_complete(fetch_url(loop,url))
async def my_background_task():
print("starting BG task")
await client.wait_until_ready()
while not client.is_closed:
await my_method.("www.theinternet.com/restcall").json()["dict_element"]
#do more stuff
So I now try to work with aiohttp but run into issues with async loops within this loop.
I haven't found a proper explanation on how to approach this. I'm pretty new to python and async functions.
Upvotes: 0
Views: 1843
Reputation: 4241
Without the error you get from your aiohttp version, it's hard to guess. But at first sight, I would say that :
ClientSession
, it will automatically choose the current event loop, so you should just call ClientSession()
fetch
function should not await resp
. resp
is not a coroutine there. You probably want to return await resp.json()
(and remove the extra .json()
in my_background_task
)my_method
, you are already running in a coroutine, as indicated by the async def
. So to call another coroutine, you should be await
-ing it, not creating a new event loop and running it in that new loop.my_background_task
, you are awaiting something that does not make any sense: check the operator priority of await, you are calling .__getitem__
on a coroutine, and then awaiting the result of __getitem__
, which is the reverse of what you want.async with
, ie as soon as the fetch
method is done).my_background_task
and use it-
async def fetch(session, url):
async with session.get(url) as resp:
print(resp.status)
return await resp.json()
async def my_background_task()
print("starting BG task")
await client.wait_until_ready()
async with aiohttp.ClientSession() as session:
while not client.is_closed:
data = await fetch(session, "www.theinternet.com/restcall")
element = data["dict_element"]
Upvotes: 1
Reputation: 2628
I got around this by having another background task that keeps the http response as a global variable and updates it on its own.
I'm no sure if that's the way I'm supposed to do it, but that's what got me out of a pickle.
Upvotes: 0