Python 协程全套核心模块
协程:单线程下并发,IO 等待时切换任务,开销远小于多线程,爬虫、接口压测、异步服务最常用。
核心内置模块:asyncio(Python3.4 + 自带,官方标准协程库)
配套常用拓展库:aiohttp、aiomysql、redis-py 异步版等
一、基础核心概念先理清
- async 关键字:定义协程函数,调用不会立刻执行,返回协程对象
- await:只能写在 async 函数内部,等待耗时 IO 操作(让出 CPU,切换其他任务)
- 事件循环 loop:协程调度器,负责管理、执行所有协程任务
- Task:将协程打包成任务,支持并发运行多个协程
二、asyncio 常用 API + 逐行可运行示例
示例 1:最简单协程入门(基础语法)
python
运行
import asyncio
# 1. 定义协程函数
async def hello():
print("开始执行")
# 异步休眠:await 让出CPU,不会阻塞整个线程
await asyncio.sleep(2)
print("执行完毕")
if __name__ == "__main__":
# 方式1:Python3.7+ 推荐极简写法(自动创建、关闭事件循环)
asyncio.run(hello())
示例 2:多个协程并发执行(核心用法)
同时跑多个任务,总耗时≈2s,串行需要 4s,体现协程并发优势
python
运行
import asyncio
async def task(name, delay):
print(f"任务{name}启动,等待{delay}秒")
await asyncio.sleep(delay)
print(f"任务{name}完成")
async def main():
# 创建多个协程任务
t1 = asyncio.create_task(task("A", 2))
t2 = asyncio.create_task(task("B", 2))
# 等待所有任务执行结束
await t1
await t2
if __name__ == "__main__":
asyncio.run(main())
示例 3:asyncio.gather () 批量并发(最常用)
一次性收集所有协程,等待全部完成,统一接收返回结果
python
运行
import asyncio
async def do_work(num):
await asyncio.sleep(1)
return f"结果{num}"
async def main():
# 批量打包多个协程并发执行
res_list = await asyncio.gather(
do_work(1),
do_work(2),
do_work(3)
)
# 返回有序结果列表
print(res_list) # ['结果1', '结果2', '结果3']
asyncio.run(main())
示例 4:设置协程超时(避免卡死)
python
运行
import asyncio
async def long_task():
await asyncio.sleep(5)
return "完成"
async def main():
try:
# 最多等待3秒,超时直接抛出异常
result = await asyncio.wait_for(long_task(), timeout=3)
print(result)
except asyncio.TimeoutError:
print("任务超时终止")
asyncio.run(main())
示例 5:asyncio.wait 区分完成 / 未完成任务
python
运行
import asyncio
async def func(n):
await asyncio.sleep(n)
return n
async def main():
tasks = [asyncio.create_task(func(1)), asyncio.create_task(func(3))]
done, pending = await asyncio.wait(tasks, timeout=2)
# done:已完成任务;pending:超时未结束任务
print("已完成:", [t.result() for t in done])
asyncio.run(main())
三、协程常用第三方异步模块(测试 / 爬虫高频)
1. aiohttp 异步 HTTP 请求(接口自动化、异步爬虫首选)
对标同步 requests,异步发请求,上万接口并发效率极高
安装:
pip install aiohttppython
运行
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as resp:
return await resp.json()
async def main():
# 创建异步会话
async with aiohttp.ClientSession() as session:
# 并发请求多个接口
urls = [
"https://httpbin.org/get",
"https://httpbin.org/headers"
]
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)
print(results)
asyncio.run(main())
2. aiomysql:异步操作 MySQL 数据库
同步:pymysql | 异步:aiomysql,大量数据库查询场景提速明显
安装:
pip install aiomysql3. aioredis:异步 Redis 客户端
异步读写缓存,压测、高并发场景使用
四、面试高频考点
- 协程、线程、进程区别
- 进程:资源隔离,开销最大,多核利用
- 线程:操作系统调度,IO 密集型适用,有 GIL 锁限制 CPU 运算
- 协程:用户态调度,单线程内切换,开销最小,只适合 IO 密集场景
- GIL 全局解释器锁:Python 同一时刻只有 1 个线程执行 CPU 代码,所以计算密集用多进程,IO 密集用多线程 / 协程
- await 只能跟可等待对象:协程、Task、Future
- 老版本 loop 写法(了解即可)
python
运行
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
loop.close()
五、易错点总结
- 普通函数不能 await,必须加 async
- time.sleep () 是同步阻塞!协程里一定要用
asyncio.sleep() - 不能在循环里串行 await,要用 create_task/gather 实现并发
浙公网安备 33010602011771号