同步代码像老牛拉车,一个请求卡住,整个服务就干瞪眼。
协程却能让你的程序“一心多用”,I/O等待时自动切到下一个任务。
实测数据很打脸:某API网关引入asyncio后,单机QPS从1200飙到4800!🚀
async/await?没你想的那么难!
import asyncio
asyncdefbrew_coffee():
print("☕ 开始煮咖啡...")
await asyncio.sleep(2) # 模拟I/O等待
print("☕ 咖啡好了!")
asyncdeftoast_bread():
print("🍞 开始烤面包...")
await asyncio.sleep(1)
print("🍞 面包好了!")
asyncdefmain():
# 两个任务同时启动,总耗时≈2秒,不是3秒!
await asyncio.gather(brew_coffee(), toast_bread())
asyncio.run(main())
看懂没?async定义协程,await挂起当前任务。
核心就一点:别在async函数里调用任何阻塞操作,比如time.sleep()或普通文件读写。
协程≠线程,别搞混了!
很多人以为协程是“轻量级线程”,这说法害人不浅。
线程是操作系统调度的,会抢资源、要加锁;协程是程序自己调度的,天生协作,无需锁。
它只适合I/O密集型场景(网络、数据库),CPU密集型?该用multiprocessing就用,别硬上。
性能不够?上uvloop!快如闪电⚡
Python默认的事件循环是纯Python写的,有点“肉”。
uvloop 是它的C语言超频版,基于Node.js同款libuv引擎。
只需两行代码,性能直接起飞:
import uvloop
uvloop.install() # 替换默认循环
# 你原来的asyncio代码一行都不用改!
asyncio.run(main())
官方实测:吞吐量提升2-5倍,高并发下延迟更低。这波升级,血赚不亏!
避坑指南:这些雷千万别踩!
- **别在协程里用
requests**!它是同步阻塞的。要用aiohttp或httpx。 - **别滥用
asyncio.create_task()**。任务创建太多会撑爆内存,用semaphore限流。 - 错误处理要小心!协程里的异常不会自动抛出,记得用
try/except包裹await。
# 正确姿势:限制并发数
asyncdefdownload(sem, url):
asyncwith sem: # 控制并发
asyncwith aiohttp.ClientSession() as session:
asyncwith session.get(url) as resp:
returnawait resp.text()
asyncdefmain():
sem = asyncio.Semaphore(10) # 最多10个并发
tasks = [download(sem, f"https://example.com/{i}") for i in range(100)]
await asyncio.gather(*tasks)
写在最后:协程是把双刃剑
用得好,你的服务能扛住流量洪峰;用不好,代码又臭又难调试。
记住:异步不是银弹。先分析瓶颈是不是I/O,再决定是否重构。
别为了炫技而异步,稳定和可维护性永远排第一。