文章
Python的asyncio
asyncio的基本使用
目录
下面从“基本用法”和“典型场景”两方面来介绍 Python asyncio。#
一、基本用法#
1.1 启动事件循环#
import asyncio
async def main():
print("Hello")
await asyncio.sleep(1)
print("World")
# Python 3.7+ 推荐写法
asyncio.run(main())
async def定义一个 协程函数(coroutine function),调用它将返回一个协程对象(coroutine)。await用于在协程内部挂起当前任务,等待另一个协程或 Future 完成。asyncio.run(...)会创建并管理一个事件循环,将指定的顶层协程运行到完成,然后关闭循环。
1.2 任务(Task)和并发执行#
import asyncio
async def worker(name, delay):
await asyncio.sleep(delay)
print(f"{name} 完成,耗时 {delay}s")
async def main():
# 三个任务并发启动
t1 = asyncio.create_task(worker("任务A", 2))
t2 = asyncio.create_task(worker("任务B", 1))
t3 = asyncio.create_task(worker("任务C", 3))
# 等待所有任务完成
await asyncio.gather(t1, t2, t3)
asyncio.run(main())
asyncio.create_task(coro):将协程包装成 Task,交给事件循环调度。asyncio.gather(...):并发地等待一组协程或 Task,返回它们的结果列表。
1.3 控制并发量:信号量(Semaphore)#
import asyncio
from random import random
sem = asyncio.Semaphore(3) # 同时最多 3 个并发
async def bound_worker(i):
async with sem:
delay = random() * 2
await asyncio.sleep(delay)
print(f"工作 {i} 完成({delay:.2f}s)")
async def main():
tasks = [asyncio.create_task(bound_worker(i)) for i in range(10)]
await asyncio.gather(*tasks)
asyncio.run(main())
asyncio.Semaphore(n)用来限制并发量,防止同时启动过多操作(如 HTTP 请求)而导致资源枯竭。
1.4 超时管理:wait_for#
import asyncio
async def long_op():
await asyncio.sleep(5)
return "结果"
async def main():
try:
# 最多等 2 秒,超时则抛 TimeoutError
res = await asyncio.wait_for(long_op(), timeout=2)
print(res)
except asyncio.TimeoutError:
print("操作超时")
asyncio.run(main())
二、典型使用场景#
- 高并发网络 IO
- HTTP 客户端/爬虫:同时对上百甚至上千个目标发起请求,用
aiohttp或httpx.AsyncClient。 - WebSocket 客户端/服务器:实时双向通信,用
websockets或aiohttp的 WebSocket 支持。
- HTTP 客户端/爬虫:同时对上百甚至上千个目标发起请求,用
- 异步 Web 服务
- 框架如 FastAPI、aiohttp.web、Sanic 等,基于
asyncio,可以在单个进程中高效地并发处理大量 HTTP 请求。
- 框架如 FastAPI、aiohttp.web、Sanic 等,基于
- 数据库异步驱动
- 异步 ORM/驱动:
databases+SQLAlchemy、asyncpg(PostgreSQL)、aiomysql(MySQL),有助于在使用协程的服务中避免阻塞。
- 异步 ORM/驱动:
- 消息队列与后台任务
- 与 RabbitMQ、Kafka、Redis Stream 等异步交互,使用
aio-pika、aiokafka、aredis等库,实现高吞吐的消息消费。
- 与 RabbitMQ、Kafka、Redis Stream 等异步交互,使用
- 异步定时与调度
- 周期性任务:在事件循环内用
asyncio.sleep或aiocron定时执行定时器逻辑。
- 周期性任务:在事件循环内用
- 并行化文件 IO
- 虽然 Python 标准库文件 IO 是同步的,但通过
aiofiles可实现异步读写,适用于大量磁盘操作场景。
- 虽然 Python 标准库文件 IO 是同步的,但通过
三、小结#
- 优点:在单线程下用协作式多任务(协程)来高效并发处理大量 IO 操作,节省线程/进程开销。
- 缺点:CPU 密集型任务依旧需要使用多线程或多进程;需要第三方库支持异步接口。
- 选型建议:
- 如果你项目主要瓶颈在网络/IO,且有高并发需求,
asyncio+ 异步库 是首选。 - 如果只是简单脚本或 CPU 密集型运算,则普通同步或多进程/多线程更易实现。
希望这些示例和场景能帮助你上手并正确选用
asyncio!
- 如果你项目主要瓶颈在网络/IO,且有高并发需求,