如何正确使用Python async功能?结合两类异步场景求解
Python Async异步核心用法:两类场景实战解析
模型A:串行依赖的异步调用(函数#3 → #2 → #1)
这种场景下,函数间存在明确的依赖关系——必须等上游函数执行完成并返回结果,下游函数才能继续执行。此时await的作用就是暂停当前协程,等待依赖的异步任务完成,拿到结果后再恢复执行。
举个实际代码例子:
import asyncio async def func1(): print("开始执行func1") await asyncio.sleep(2) # 模拟IO操作,比如网络请求、文件读取 return "func1的结果" async def func2(): print("开始执行func2,等待func1完成") result1 = await func1() await asyncio.sleep(1) return f"func2处理了[{result1}]后的结果" async def func3(): print("开始执行func3,等待func2完成") result2 = await func2() return f"func3最终输出:[{result2}]" async def main(): final_result = await func3() print(final_result) asyncio.run(main())
执行顺序是严格串行的:func3启动后先等func2,func2启动后等func1,func1完成后func2继续,func2完成后func3继续。整个流程总耗时约3秒(2+1),因为每一步都必须等前一步结束。
模型B:独立分支的并行异步调用
当两个任务完全独立、互不依赖时,就可以利用异步的优势让它们并行执行,避免不必要的等待。这里的关键是不要挨个await(那样会变成串行),而是用asyncio.gather()或者asyncio.create_task()来让事件循环同时调度多个协程。
错误示例(串行执行,浪费时间)
import asyncio async def task_a(): print("启动task_a") await asyncio.sleep(3) return "task_a完成" async def task_b(): print("启动task_b") await asyncio.sleep(2) return "task_b完成" async def main(): # 挨个await会导致先等task_a完成,再启动task_b,总耗时5秒 result_a = await task_a() result_b = await task_b() print(result_a, result_b) asyncio.run(main())
正确示例(并行执行,节省时间)
用asyncio.gather()一次性调度多个协程:
import asyncio async def task_a(): print("启动task_a") await asyncio.sleep(3) return "task_a完成" async def task_b(): print("启动task_b") await asyncio.sleep(2) return "task_b完成" async def main(): # 同时启动两个任务,事件循环会在它们等待IO时切换执行 result_a, result_b = await asyncio.gather(task_a(), task_b()) print(result_a, result_b) asyncio.run(main())
或者用create_task显式创建任务对象:
async def main(): task1 = asyncio.create_task(task_a()) task2 = asyncio.create_task(task_b()) result_a = await task1 result_b = await task2 print(result_a, result_b)
这两种写法的总耗时都是3秒(取最长任务的耗时),因为两个任务是并行执行的。
关键注意点
await只能在异步函数(用async def定义)内部使用,它的作用是暂停当前协程,把控制权交还给事件循环,让其他协程有机会运行。- 异步编程的优势主要体现在IO密集型任务(比如网络请求、数据库操作、文件读写),如果是CPU密集型任务,异步的效率不如多进程,因为Python的GIL锁会限制CPU并行。
内容的提问来源于stack exchange,提问作者zezo
相关产品推荐
相关产品推荐

