如何修正Python异步函数中的同步循环以实现并发请求
解决方案
核心是把两层循环中每个请求对应的协程任务收集起来,通过asyncio.gather()批量并发执行,替代逐次await的同步逻辑。以下是具体实现方式:
步骤1:重构任务生成逻辑
先把需要请求的所有URL对应的协程任务统一收集,避免在循环内逐个await导致串行执行,让所有请求能同时发起。
步骤2:修改主逻辑实现并发
下面是调整后的完整代码示例(假设你原代码的数据源结构如下):
import aiohttp import asyncio async def fetch(session, url): async with session.get(url) as response: # 可根据需求替换为响应解析逻辑,比如response.json() return await response.text() async def main(): # 示例两层循环的数据源 categories = ["books", "electronics", "clothing"] item_ids = [101, 102, 103] async with aiohttp.ClientSession() as session: # 收集所有请求任务 tasks = [] for category in categories: for item_id in item_ids: url = f"https://example.com/api/{category}/{item_id}" # 创建协程对象,暂不执行 tasks.append(fetch(session, url)) # 并发执行所有任务,等待全部完成 results = await asyncio.gather(*tasks) # 按顺序处理结果(结果顺序与tasks列表顺序完全对应) for idx, result in enumerate(results): category = categories[idx // len(item_ids)] item_id = item_ids[idx % len(item_ids)] print(f"完成 {category}-{item_id} 请求,响应摘要: {result[:50]}...") if __name__ == "__main__": asyncio.run(main())
额外优化建议
- 限制并发数:如果请求量极大(比如数百上千个),可以用
asyncio.Semaphore避免触发目标服务器限流:async def main(): categories = ["books", "electronics", "clothing"] item_ids = [101, 102, 103] # 限制同时最多10个并发请求 semaphore = asyncio.Semaphore(10) async def bounded_fetch(session, url): async with semaphore: return await fetch(session, url) async with aiohttp.ClientSession() as session: tasks = [bounded_fetch(session, f"https://example.com/api/{c}/{i}") for c in categories for i in item_ids] results = await asyncio.gather(*tasks) # 后续处理逻辑不变 - 容错处理:给
asyncio.gather()添加return_exceptions=True,单个请求失败不会导致整个任务组崩溃,而是返回异常对象便于排查:results = await asyncio.gather(*tasks, return_exceptions=True)
内容的提问来源于stack exchange,提问作者automation_m
相关产品推荐
相关产品推荐

