Python3.8 asyncio异步API调用报错求助:协程与类型错误
问题排查与解决方案
核心错误原因
- 函数名不匹配:客户端定义的异步函数是
get_product_by_id_async,但协调函数中误用了get_product_by_id(推测该函数为同步实现,直接返回dict),导致await非协程对象触发TypeError。 - 任务创建方式错误:在列表推导式中逐个
await调用会让请求串行执行,既失去异步并发的意义,还会因为同步函数返回的dict无法被await而报错。
修正后的代码
客户端代码(优化异步API调用)
from typing import Optional import httpx async def get_product_by_id_async(self, product_id: str) -> Optional[dict]: if product_id is None: return None try: # 确保async_client是httpx.AsyncClient实例 response = await self.async_client.get( url=f"{self.base_url}/api/catalog/stock{product_id}", headers=self.headers, timeout=10.0 # 添加超时避免阻塞 ) response.raise_for_status() # 主动触发HTTP状态码异常 return response.json() # 用httpx内置方法解析JSON,替代手动json.loads except httpx.HTTPError as e: print(f"获取产品ID {product_id} 失败: {str(e)}") return None
协调函数(实现真正异步并发)
import asyncio import pandas as pd async def async_get_products(data_parser): path = data_parser.options["path"] sku_list = client.run() products_list = [] # 1. 创建协程任务列表(不在这里await,实现并发) tasks = [client.get_product_by_id_async(sku) for sku in sku_list] # 2. 并发等待所有任务完成,return_exceptions=True可避免单个失败导致整体崩溃 completed = await asyncio.gather(*tasks, return_exceptions=True) # 过滤有效结果(排除None和异常) for result in completed: if isinstance(result, dict): products_list = build_product_df(products_list, result) products_df = pd.DataFrame(products_list) products_df.to_csv(path, index=False) return products_df def products_processor_concurrent(data_parser): # 用asyncio.run运行顶层协程,替代直接返回协程对象 return asyncio.run(async_get_products(data_parser))
额外说明
- 确保
self.async_client是httpx.AsyncClient实例,而非同步的httpx.Client,否则异步调用无法正常工作。 return_exceptions=True参数可以让asyncio.gather在单个任务失败时继续执行其他任务,失败结果会以异常对象形式返回,方便后续排查。
内容的提问来源于stack exchange,提问作者bittrago
相关产品推荐
相关产品推荐

