Issue
I found myself wondering if aiohttp.ClientSession() would return results sequentially because it was supposed to call a server many times, and then wait for all of the replies to arrive. I was expecting the results to be returned in a non-sequential order.
Additionally, the rate of replies varied, but strangely enough, they still remained in sequence.
I ran the below code multiple times:
async def main():
async with aiohttp.ClientSession() as session:
res_dict={}
for number in range(1, 100):
pokemon_url = f'https://pokeapi.co/api/v2/pokemon/{number}'
async with session.get(pokemon_url) as resp:
pokemon = await resp.json()
res_dict[number]=pokemon['id']
print(pokemon['id'])
for i in res_dict:
print(i, '=',res_dict[i])
asyncio.run(main())
And every time I ran it, I received the results in a perfectly ordered reply:
1 2 3 . . . 98 99
And they were also correctly paired up with each of their dict Keys as well:
1=1 2=2 3=3 . . . 98=98 99=99
Would I be correct to assume that like asyncio.gather(), an aiohttp.ClientSession object's .get() method will make queries and receive them asynchronously, only listing them if they arrive in order? I also noticed that the rate of replies being received varied, and that could be a possible explanation as to why this is happening.
Solution
Your assumption is correct. With quite a bit of modification, you can get async requests in a gather
by creating a set of tasks
like this:
import aiohttp
import asyncio
async def main():
res_dict = {}
# list of urls
urls = []
for number in range(1,20):
pokemon_url = f'https://pokeapi.co/api/v2/pokemon/{number}'
urls.append(pokemon_url)
# list of tasks (with the gather)
tasks = [asyncio.create_task(get_pokies(url)) for url in urls]
responses = await asyncio.gather(*tasks)
# make the dict
for i, response in enumerate(responses):
res_dict[i] = response['id']
print(res_dict)
async def get_pokies(url):
''' async func for the reqest '''
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
asyncio.run(main())
This will be much faster than the original code in the question, since now the requests are made "in parallel" as opposed to "in series"...
Answered By - D.L
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.