Python async/await在range循环中不生效问题咨询及代码示例
Python async/await 遍历循环无预期效果问题解答
根本原因
你遇到的问题核心是asyncio 单线程事件循环无法并行执行无 await 让出控制权的 CPU 密集型代码,你的take_time协程虽然加了async关键字,但全程没有释放事件循环的执行权,多个任务本质是串行执行,自然达不到异步加速的预期。
具体问题分析
- 你写的
take_time函数内部是纯 CPU 计算的同步for循环,全程没有await语句主动让出执行权,事件循环执行该协程时会被完全阻塞,直到循环跑完才会调度下一个任务,4个任务的总耗时基本等于单个任务耗时的4倍,和普通同步for循环串行执行没有区别。 - 你注释掉的
await asyncio.sleep(4)是异步休眠逻辑,执行到这行时会主动让出事件循环控制权,让其他待调度任务可以运行,所以如果取消这行注释,4个任务的总耗时会稳定在4秒左右,符合异步并行的预期。
解决方案
如果你的场景是处理 CPU 密集型任务,有两种可行方案:
方案1:直接用多进程替代 asyncio
CPU 密集型场景本身不适合使用 asyncio 实现并行,直接用concurrent.futures.ProcessPoolExecutor开多进程执行,就能拿到线性并行加速的效果,示例代码如下:
import time from concurrent.futures import ProcessPoolExecutor def take_time(): for i in range(100000000): o=i return str(o) def test(): response = {} s = time.time() with ProcessPoolExecutor() as executor: answers = list(executor.map(take_time, [None]*4)) response['ans'] = answers response["Time Taken"] = round((time.time() - s),2) print(response) return response if __name__=='__main__': test()
方案2:asyncio 结合进程池执行 CPU 任务
如果一定要保留 asyncio 框架,可以将 CPU 密集型逻辑扔到独立进程池运行,避免阻塞事件循环,用loop.run_in_executor包裹同步计算逻辑即可,示例代码如下:
import asyncio import time from concurrent.futures import ProcessPoolExecutor async def test(): response = {} s = time.time() loop = asyncio.get_running_loop() # 把CPU密集型任务放到进程池执行 with ProcessPoolExecutor() as pool: tasks = [loop.run_in_executor(pool, take_time) for _ in range(4)] answers = await asyncio.gather(*tasks) response['ans'] = answers response["Time Taken"] = round((time.time() - s),2) print(response) return response def take_time(): for i in range(100000000): o=i return str(o) if __name__=='__main__': asyncio.run(test())
核心规则说明
async关键字仅标识函数为协程,不会自动实现并行,只有协程执行到await语句主动让出控制权时,事件循环才会调度其他待执行任务。- asyncio 仅适合 IO 密集型场景(网络请求、文件读写、数据库查询等),CPU 密集型场景优先使用多进程实现并行。
内容的提问来源于stack exchange,提问作者Raja Raghudeep Emani
相关产品推荐
相关产品推荐

