为何我的Python aiohttp请求代码无法异步运行?
解决aiohttp循环请求阻塞的问题
你的代码看似用了异步框架,但实际是串行执行的,所以每次迭代都会阻塞。原因是在for循环里,每一次都要等待await resp.text()执行完成后才会进入下一次循环,完全没发挥异步的并发优势,和同步代码没区别。
修复方案1:用asyncio.gather实现并发请求
先把单次请求封装成独立的异步函数,再批量创建任务并发执行:
import asyncio import aiohttp async def predict_image(session, image): image_bytes = pil_to_bytes(image) async with session.post('http://localhost:8080/predictions/resnet50', data=image_bytes) as resp: return await resp.text() async def main(): async with aiohttp.ClientSession() as session: # 为每个图片创建异步任务 tasks = [predict_image(session, image) for image, target in dataset_val] # 并发执行所有任务并获取结果 results = await asyncio.gather(*tasks) # 遍历结果输出 for i, result in enumerate(results): print(result) print(i, flush=True, end='\r') asyncio.run(main())
修复方案2:用信号量控制并发数(避免压垮API)
如果数据集很大,一次性发起所有请求可能会给API服务造成压力,这时可以用asyncio.Semaphore限制最大并发数:
import asyncio import aiohttp async def predict_image(session, semaphore, image): async with semaphore: # 控制并发数 image_bytes = pil_to_bytes(image) async with session.post('http://localhost:8080/predictions/resnet50', data=image_bytes) as resp: return await resp.text() async def main(): max_concurrent = 10 # 设置最大并发请求数 semaphore = asyncio.Semaphore(max_concurrent) async with aiohttp.ClientSession() as session: tasks = [predict_image(session, semaphore, image) for image, target in dataset_val] results = await asyncio.gather(*tasks) for i, result in enumerate(results): print(result) print(i, flush=True, end='\r') asyncio.run(main())
这两种写法都会让请求同时发起,大幅减少整体耗时,解决循环阻塞的问题。
内容的提问来源于stack exchange,提问作者Terv
相关产品推荐
相关产品推荐

