Python asyncio 异步编程
欢迎学习 Python asyncio 异步编程!本教程将带你从零基础开始,全面掌握 Python 异步编程的核心知识和实战技能。
什么是 asyncio?
asyncio 是 Python 3.4 引入的标准库,用于编写并发代码。它使用 async/await 语法,让开发者能够以同步代码的风格编写异步程序。
asyncio 是多个 Python 异步框架的基础,包括高性能网络服务器、Web 框架、数据库连接库、分布式任务队列等。
核心特点
- 协程支持:使用
async def定义协程,await等待异步操作 - 事件循环:单线程事件循环管理所有异步任务
- 非阻塞 I/O:网络请求、文件操作等不会阻塞程序执行
- 结构化并发:TaskGroup 等机制确保任务安全执行
- 丰富的同步原语:Lock、Event、Semaphore、Queue 等
同步 vs 异步
理解同步和异步的区别是掌握 asyncio 的第一步:
同步编程:代码按顺序执行,每个操作完成后再执行下一个。
import time
def fetch_data():
time.sleep(1) # 阻塞等待
return "数据"
def main():
data1 = fetch_data() # 等待 1 秒
data2 = fetch_data() # 再等待 1 秒
print(data1, data2)
main() # 总耗时约 2 秒
异步编程:多个操作可以"并行"进行,等待时执行其他任务。
import asyncio
async def fetch_data():
await asyncio.sleep(1) # 非阻塞等待
return "数据"
async def main():
# 同时发起两个请求
task1 = asyncio.create_task(fetch_data())
task2 = asyncio.create_task(fetch_data())
data1 = await task1
data2 = await task2
print(data1, data2)
asyncio.run(main()) # 总耗时约 1 秒
异步编程的核心优势在于:当一个任务在等待(如网络请求、磁盘 I/O)时,程序可以切换到其他任务执行,从而提高整体效率。
适用场景
asyncio 特别适合以下场景:
| 场景 | 说明 |
|---|---|
| 网络爬虫 | 同时抓取多个网页 |
| Web 服务器 | 处理大量并发请求 |
| API 客户端 | 并发调用多个外部 API |
| 数据库操作 | 异步数据库查询 |
| 实时通信 | WebSocket、聊天服务器 |
| 微服务调用 | 并发调用多个后端服务 |
不适合的场景:CPU 密集型任务(计算密集型操作),这类任务应使用多进程(multiprocessing)。
asyncio 的核心组件
asyncio 提供了层次分明的 API 结构:
高层 API
应用开发者主要使用这些 API:
- 协程与任务:
async def、await、create_task、gather、TaskGroup - 异步队列:
Queue、PriorityQueue、LifoQueue - 同步原语:
Lock、Event、Condition、Semaphore、Barrier - 异步上下文管理器:
async with语法 - 异步迭代器:
async for语法
低层 API
库和框架开发者使用这些 API:
- 事件循环:
get_event_loop、run_until_complete - 传输与协议:自定义底层协议
- Future 对象:底层异步操作结果
本教程主要关注高层 API,这是大多数应用开发所需的。
为什么学习 asyncio?
1. 现代 Python 开发的标配
Python 3.7+ 正式将 async/await 作为关键字,异步编程已成为 Python 生态的重要组成部分。主流框架纷纷支持异步:
- Web 框架:FastAPI、Starlette、Sanic、aiohttp
- 数据库:asyncpg、aiomysql、motor(MongoDB)
- HTTP 客户端:aiohttp、httpx
- 任务队列:arq、dramatiq
2. 性能提升
对于 I/O 密集型应用,异步编程可以显著提升并发性能:
# 同步方式:顺序请求 100 个 URL
import requests
import time
urls = [f"https://api.example.com/{i}" for i in range(100)]
start = time.time()
for url in urls:
requests.get(url) # 每个请求等待响应
print(f"同步耗时: {time.time() - start:.2f} 秒") # 约 100 秒
# 异步方式:并发请求 100 个 URL
import aiohttp
import asyncio
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
await asyncio.gather(*tasks)
start = time.time()
asyncio.run(main())
print(f"异步耗时: {time.time() - start:.2f} 秒") # 约 1-2 秒
3. 更好的资源利用
异步程序在单线程中运行,避免了线程切换的开销和 GIL(全局解释器锁)的限制。一个异步程序可以用极低的资源处理数千个并发连接。
学习路径
基础阶段 核心阶段 进阶阶段 实战阶段
│ │ │ │
▼ ▼ ▼ ▼
协程概念 ──▶ 任务与并发 ──▶ 同步原语 ──▶ Web 应用
async/await ──▶ gather/wait ──▶ Lock/Semaphore ──▶ FastAPI
事件循环 ──▶ TaskGroup ──▶ Queue ──▶ 爬虫开发
第一个程序 ──▶ 超时控制 ──▶ 异步上下文管理器 ──▶ 数据库操作
教程目录
基础入门
核心功能
- 任务与并发 - 创建任务、TaskGroup、并发执行、取消与超时、shield 保护
同步原语
- 同步原语 - Lock、Event、Condition、Semaphore、Barrier、Queue
异步 I/O
- 异步网络编程 - TCP 客户端/服务器、UDP、SSL/TLS、Unix 套接字
高级主题
- 异步迭代器与生成器 - async for、异步生成器、异步推导式
- 异步上下文管理器 - async with、
__aenter__/__aexit__、@asynccontextmanager - 子进程管理 - 异步执行外部命令、进程交互、并发执行、管道连接
实战应用
前置知识
学习 asyncio 前需要掌握:
- Python 基础:函数、类、装饰器、上下文管理器
- 迭代器与生成器:
yield、__iter__、__next__ - 并发概念:进程、线程、并发的区别
开发环境
- Python 3.8+(推荐 3.11+,支持 TaskGroup)
- 支持 async/await 语法高亮的编辑器(VS Code、PyCharm)
快速体验
在命令行启动 asyncio REPL,直接体验异步编程:
python -m asyncio
asyncio REPL 3.11.0
Use "await" directly instead of "asyncio.run()".
>>> import asyncio
>>> await asyncio.sleep(1, result="hello")
'hello'
参考资料
准备好开始学习了吗?让我们从协程基础开始,深入理解异步编程的核心概念。