为何Python同步与异步代码执行同一逻辑返回不同类型?
问题原因与解决方法
核心差异:asyncio.gather()的返回特性
同步代码中,get_response()直接返回单个字典对象,所以type(json_response)是dict。
而异步代码里你用了asyncio.gather(get_response(user_url)),这个函数的设计逻辑是:接收一个或多个可等待对象,并发执行后返回所有结果组成的列表——哪怕只传入一个协程,它也会把结果包装成单元素列表返回,所以type(json_response)是list。
修正方案
方案1:直接await单个协程(推荐,适合单任务场景)
不需要用gather,直接await单个协程即可:
import urllib.request import json import asyncio async def get_response(user_url): resp = urllib.request.urlopen(user_url).read() resp_json = json.loads(resp) return resp_json['results'][0] async def make_request(user_url): json_response = await get_response(user_url) # 直接await单个协程 print(type(json_response)) # 输出 <class 'dict'> USER_URL = 'https://randomuser.me/api' asyncio.run(make_request(USER_URL))
方案2:若需保留gather,取列表第一个元素
如果是为了后续扩展多任务而保留gather,可以直接提取列表的第一个元素:
import urllib.request import json import asyncio async def get_response(user_url): resp = urllib.request.urlopen(user_url).read() resp_json = json.loads(resp) return resp_json['results'][0] async def make_request(user_url): json_response = (await asyncio.gather(get_response(user_url)))[0] # 取列表第一个元素 print(type(json_response)) # 输出 <class 'dict'> USER_URL = 'https://randomuser.me/api' asyncio.run(make_request(USER_URL))
补充说明
asyncio.gather()的核心用途是并发执行多个异步任务,比如同时请求多个URL时:
results = await asyncio.gather( get_response(url1), get_response(url2), get_response(url3) ) # results 是包含三个字典的列表
单任务场景下完全没必要使用它,直接await单个协程更简洁。
内容的提问来源于stack exchange,提问作者Amresh Kumar
相关产品推荐
相关产品推荐

