在Python日常开发中,普通同步代码是从上到下顺序执行。当遇到网络请求、接口访问这类IO等待场景时,程序会原地阻塞等待,CPU资源白白浪费。

模块asyncio是Python内置异步编程库,搭配async,await关键字可以实现协程并发。不需要多线程多进程,就可以高效处理IO密集型任务。

本文基于4组可直接运行的示例,分别演示串行执行、create_task并发、gather批量并发、模拟网络IO,帮你彻底搞懂异步协程。

基础概念:

(1)async def:定义异步协程函数,调用函数得到协程对象,不会直接执行函数体

(2)await:只能写在async函数内部,挂起当前协程,让出CPU,等待IO完成

(3)asyncio.run():启动事件循环的入口

一、串行执行:普通 await 顺序调用

直接使用await依次调用异步函数,任务一个接一个执行,总时间等于所有任务时间相加,没有发挥并发优势

总耗时:1+2=3秒

特点:执行完第一个任务,才会启动第二个任务。适合任务有先后依赖的场景。

二、使用 create_task 实现真正并发

asyncio.create_task()把协程包装成Task任务,交给事件循环,多个任务同时启动并发等待。不再时间累加,总耗时等于耗时最长的那个任务。

总耗时:3秒

两个任务几乎同时开启,任务1耗时1秒先结束,程序继续等待耗时3秒的任务2完成。总时间取最大值,不是相加。

三、asyncio.gather 批量调度协程

当任务数量很多时,一个个写create_task比较繁琐。asyncio.gather()可以一次性传入大量协程,统一并发执行,并且收集所有任务的 return 返回值,返回一个结果列表。

总耗时:6秒

三个任务同时运行,最大延时为 3*2=6秒。gather会保存每个任务return的数据,存入列表返回。

四、实战模拟:模拟网络 IO 请求场景

异步最大用处就是网络IO(爬虫、接口请求)。下面模拟并发请求多个url,用asyncio.sleep模拟网络延时。

异步不会让单个任务变快,只是利用 IO 等待间隙同时处理多个任务。串行耗时累加,并发看最长任务耗时。

记住两个常用写法:少量任务用create_task,批量任务要拿返回结果用asyncio.gather()。 切忌混用time.sleep()阻塞事件循环,参数传递也要格外小心。

多动手运行调试代码,就能快速掌握async/await协程。感谢阅读

更多推荐