英文:
Why does aiohttp.ClientSession() object .get() Method Return Results In Order Even Though It Is Asynchronous?
问题
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.
此刻我在想,aiohttp.ClientSession()是否会按顺序返回结果,因为它应该多次调用服务器,然后等待所有回复都到达。我原本期望结果不是按顺序返回。
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.
我是否可以合理地假设,类似于asyncio.gather(),aiohttp.ClientSession对象的.get()方法将异步地发出查询并接收它们,只有在它们按顺序到达时才将它们列出?我还注意到,接收到的回复速率各不相同,这可能是发生这种情况的可能解释。
英文:
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.
答案1
得分: 1
你的假设是正确的。通过进行相当多的修改,您可以通过创建一组类似以下方式的tasks
在gather
中获取异步请求:
import aiohttp
import asyncio
async def main():
res_dict = {}
# URL列表
urls = []
for number in range(1, 20):
pokemon_url = f'https://pokeapi.co/api/v2/pokemon/{number}'
urls.append(pokemon_url)
# 任务列表(包括gather)
tasks = [asyncio.create_task(get_pokies(url)) for url in urls]
responses = await asyncio.gather(*tasks)
# 创建字典
for i, response in enumerate(responses):
res_dict[i] = response['id']
print(res_dict)
async def get_pokies(url):
'''用于请求的异步函数'''
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
asyncio.run(main())
这将比问题中的原始代码快得多,因为现在请求是“并行”而不是“串行”进行的。
英文:
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"...
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论