目录
在当今高并发的互联网应用中,异步编程已经成为提升性能的关键技术。Python通过asyncio库提供了强大的异步编程支持,而FastAPI则是在此基础上构建的现代化Web框架。本文将深入探讨Python异步编程的核心概念、实践技巧以及FastAPI框架的高级应用。

一、异步编程基础概念
1.1 同步 vs 异步
同步编程的特点是顺序执行,每个操作必须等待前一个操作完成后才能开始。而异步编程允许程序在等待I/O操作时继续执行其他任务,大大提高了程序的并发性能。
1.2 事件循环(Event Loop)
事件循环是异步编程的核心,它负责调度和执行异步任务。Python的asyncio库提供了完善的事件循环机制。
import asyncio
async def main():
print('Hello')
await asyncio.sleep(1)
print('World')
# 运行异步函数
asyncio.run(main())
1.3 协程(Coroutine)
协程是异步编程的基本单位,使用async def定义,通过await关键字等待异步操作完成。
import asyncio
async def fetch_data(delay, id):
print(f"开始获取数据 {id}")
await asyncio.sleep(delay)
print(f"数据 {id} 获取完成")
return f"数据 {id}"
async def main():
# 同时执行多个协程
tasks = [
fetch_data(2, 1),
fetch_data(1, 2),
fetch_data(3, 3)
]
results = await asyncio.gather(*tasks)
print(f"所有任务完成: {results}")
asyncio.run(main())
二、asyncio核心组件详解
2.1 Task对象
Task是asyncio中用于管理协程执行的对象,它包装协程并在事件循环中调度执行。
import asyncio
async def long_running_task(name, seconds):
print(f"任务 {name} 开始")
await asyncio.sleep(seconds)
print(f"任务 {name} 完成")
return f"任务 {name} 结果"
async def main():
# 创建任务
task1 = asyncio.create_task(long_running_task("A", 2))
task2 = asyncio.create_task(long_running_task("B", 1))
# 等待任务完成
result1 = await task1
result2 = await task2
print(f"结果: {result1}, {result2}")
asyncio.run(main())
2.2 异步上下文管理器
asyncio提供了异步上下文管理器,用于管理异步资源的生命周期。
import asyncio
class AsyncDatabaseConnection:
async def __aenter__(self):
print("连接数据库...")
await asyncio.sleep(0.5)
print("数据库连接成功")
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
print("关闭数据库连接...")
await asyncio.sleep(0.2)
print("数据库连接已关闭")
async def query(self, sql):
print(f"执行查询: {sql}")
await asyncio.sleep(0.3)
return f"查询结果: {sql}"
async def main():
async with AsyncDatabaseConnection() as db:
result = await db.query("SELECT * FROM users")
print(result)
asyncio.run(main())
2.3 异步迭代器
异步迭代器允许在异步环境中进行迭代操作。
import asyncio
class AsyncDataStream:
def __init__(self, data):
self.data = data
self.index = 0
def __aiter__(self):
return self
async def __anext__(self):
if self.index >= len(self.data):
raise StopAsyncIteration
# 模拟异步数据获取
await asyncio.sleep(0.1)
item = self.data[self.index]
self.index += 1
return item
async def main():
data_stream = AsyncDataStream([1, 2, 3, 4, 5])
async for item in data_stream:
print(f"接收到数据: {item}")
asyncio.run(main())
三、高级异步编程技巧
3.1 信号量控制并发
使用Semaphore限制同时执行的协程数量,防止资源过度占用。
import asyncio
async def worker(semaphore, name, work_time):
async with semaphore:
print(f"工人 {name} 开始工作")
await asyncio.sleep(work_time)
print(f"工人 {name} 完成工作")
return f"工作 {name} 完成"
async def main():
# 限制同时只能有2个工人工作
semaphore = asyncio.Semaphore(2)
tasks = []
for i in range(5):
task = asyncio.create_task(
worker(semaphore, f"Worker-{i}", i+1)
)
tasks.append(task)
results = await asyncio.gather(*tasks)
print("所有工作完成:", results)
asyncio.run(main())
3.2 异步队列
asyncio.Queue用于在协程之间安全地传递数据。
import asyncio
import random
async def producer(queue, name):
for i in range(3):
item = f"产品 {name}-{i}"
await asyncio.sleep(random.uniform(0.1, 0.5))
await queue.put(item)
print(f"生产者 {name} 生产了: {item}")
# 发送结束信号
await queue.put(None)
async def consumer(queue, name):
while True:
item = await queue.get()
if item is None:
# 将结束信号放回队列,让其他消费者也能收到
await queue.put(None)
break
print(f"消费者 {name} 消费了: {item}")
await asyncio.sleep(random.uniform(0.2, 0.8))
queue.task_done()
async def main():
queue = asyncio.Queue()
# 创建生产者和消费者
producers = [
asyncio.create_task(producer(queue, "A")),
asyncio.create_task(producer(queue, "B"))
]
consumers = [
asyncio.create_task(consumer(queue, "X")),
asyncio.create_task(consumer(queue, "Y"))
]
# 等待所有生产者完成
await asyncio.gather(*producers)
# 等待队列清空
await queue.join()
# 取消消费者任务
for consumer_task in consumers:
consumer_task.cancel()
asyncio.run(main())
四、FastAPI框架实战
4.1 FastAPI基础应用
FastAPI是基于asyncio的现代化Web框架,具有自动API文档生成、类型提示等特性。
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
import asyncio
app = FastAPI(title="异步API示例", version="1.0.0")
class User(BaseModel):
id: int
name: str
email: str
age: Optional[int] = None
class UserCreate(BaseModel):
name: str
email: str
age: Optional[int] = None
# 模拟数据库
fake_db = []
current_id = 1
@app.get("/")
async def root():
return {"message": "欢迎使用异步API"}
@app.get("/users", response_model=List[User])
async def get_users():
# 模拟异步数据库查询
await asyncio.sleep(0.1)
return fake_db
@app.get("/users/{user_id}", response_model=User)
async def get_user(user_id: int):
await asyncio.sleep(0.1)
for user in fake_db:
if user["id"] == user_id:
return user
raise HTTPException(status_code=404, detail="用户不存在")
@app.post("/users", response_model=User)
async def create_user(user: UserCreate):
global current_id
await asyncio.sleep(0.1)
new_user = {
"id": current_id,
**user.dict()
}
fake_db.append(new_user)
current_id += 1
return new_user
@app.put("/users/{user_id}", response_model=User)
async def update_user(user_id: int, user: UserCreate):
await asyncio.sleep(0.1)
for index, existing_user in enumerate(fake_db):
if existing_user["id"] == user_id:
fake_db[index] = {
"id": user_id,
**user.dict()
}
return fake_db[index]
raise HTTPException(status_code=404, detail="用户不存在")
@app.delete("/users/{user_id}")
async def delete_user(user_id: int):
await asyncio.sleep(0.1)
for index, user in enumerate(fake_db):
if user["id"] == user_id:
del fake_db[index]
return {"message": "用户删除成功"}
raise HTTPException(status_code=404, detail="用户不存在")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
4.2 异步数据库操作
结合SQLAlchemy和异步数据库驱动进行数据库操作。
from fastapi import FastAPI, Depends
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
import asyncio
# 数据库配置
DATABASE_URL = "sqlite+aiosqlite:///./test.db"
# 创建异步引擎
engine = create_async_engine(DATABASE_URL, echo=True)
# 创建异步会话工厂
AsyncSessionLocal = sessionmaker(
engine, class_=AsyncSession, expire_on_commit=False
)
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
email = Column(String, unique=True, index=True)
app = FastAPI()
# 依赖注入:获取数据库会话
async def get_db():
async with AsyncSessionLocal() as session:
try:
yield session
finally:
await session.close()
@app.on_event("startup")
async def startup():
# 创建数据库表
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
@app.get("/async-users")
async def get_async_users(db: AsyncSession = Depends(get_db)):
from sqlalchemy import select
# 异步查询
result = await db.execute(select(User))
users = result.scalars().all()
return {"users": [{"id": u.id, "name": u.name, "email": u.email} for u in users]}
@app.post("/async-users")
async def create_async_user(name: str, email: str, db: AsyncSession = Depends(get_db)):
new_user = User(name=name, email=email)
db.add(new_user)
await db.commit()
await db.refresh(new_user)
return {"message": "用户创建成功", "user": {"id": new_user.id, "name": new_user.name, "email": new_user.email}}
4.3 WebSocket实时通信
FastAPI支持WebSocket,可以实现实时双向通信。
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
import asyncio
import json
app = FastAPI()
# 简单的HTML页面用于测试WebSocket
html = """
<!DOCTYPE html>
<html>
<head>
<title>WebSocket测试</title>
</head>
<body>
<h1>WebSocket聊天室</h1>
<div id="messages"></div>
<input type="text" id="messageText" placeholder="输入消息">
<button onclick="sendMessage()">发送</button>
<script>
var ws = new WebSocket("ws://localhost:8000/ws");
ws.onmessage = function(event) {
var messages = document.getElementById('messages');
var message = document.createElement('div');
message.textContent = event.data;
messages.appendChild(message);
};
function sendMessage() {
var input = document.getElementById('messageText');
ws.send(input.value);
input.value = '';
}
document.getElementById('messageText').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendMessage();
}
});
</script>
</body>
</html>
"""
class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_text(message)
async def broadcast(self, message: str):
for connection in self.active_connections:
await connection.send_text(message)
manager = ConnectionManager()
@app.get("/")
async def get():
return HTMLResponse(html)
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
while True:
data = await websocket.receive_text()
await manager.broadcast(f"客户端说: {data}")
except WebSocketDisconnect:
manager.disconnect(websocket)
await manager.broadcast("有客户端断开连接")
@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: int):
await manager.connect(websocket)
try:
while True:
data = await websocket.receive_text()
await manager.send_personal_message(f"你写了: {data}", websocket)
await manager.broadcast(f"客户端 #{client_id} 说: {data}")
except WebSocketDisconnect:
manager.disconnect(websocket)
await manager.broadcast(f"客户端 #{client_id} 离开了")
五、性能优化与最佳实践
5.1 异步编程性能对比表
| 场景 | 同步方式 | 异步方式 | 性能提升 |
|---|---|---|---|
| I/O密集型任务 | 顺序执行,阻塞等待 | 并发执行,非阻塞 | 3-10倍 |
| 网络请求 | 每个请求单独线程 | 单线程处理多个请求 | 5-20倍 |
| 数据库操作 | 连接池阻塞 | 异步连接池 | 2-5倍 |
| 文件操作 | 同步读写 | 异步读写 | 2-3倍 |
5.2 最佳实践指南
- 合理使用async/await:只在真正的I/O操作前使用await
- 避免阻塞操作:不要在异步函数中执行CPU密集型任务
- 使用适当的并发控制:合理使用Semaphore、Queue等工具
- 错误处理:妥善处理异步操作中的异常
- 资源管理:使用异步上下文管理器管理资源
import asyncio
from contextlib import asynccontextmanager
@asynccontextmanager
async def async_timer(name):
start = asyncio.get_event_loop().time()
try:
yield
finally:
end = asyncio.get_event_loop().time()
print(f"{name} 执行时间: {end - start:.2f}秒")
async def optimized_async_operation():
async with async_timer("优化操作"):
# 使用gather并行执行多个异步任务
results = await asyncio.gather(
fetch_data(1),
fetch_data(2),
fetch_data(3),
return_exceptions=True # 防止一个任务失败影响其他任务
)
# 处理结果
successful_results = []
for result in results:
if not isinstance(result, Exception):
successful_results.append(result)
return successful_results
六、实战案例:异步任务调度系统
from fastapi import FastAPI, BackgroundTasks
from pydantic import BaseModel
from typing import List, Optional
import asyncio
import uuid
from datetime import datetime
app = FastAPI()
class Task(BaseModel):
id: str
name: str
status: str # pending, running, completed, failed
created_at: datetime
started_at: Optional[datetime] = None
completed_at: Optional[datetime] = None
result: Optional[str] = None
tasks_db = {}
async def execute_long_running_task(task_id: str, task_name: str):
"""模拟长时间运行的任务"""
tasks_db[task_id].status = "running"
tasks_db[task_id].started_at = datetime.now()
try:
# 模拟任务执行
await asyncio.sleep(10) # 10秒任务
# 模拟可能的错误
if "error" in task_name.lower():
raise Exception("模拟任务失败")
tasks_db[task_id].status = "completed"
tasks_db[task_id].result = f"任务 {task_name} 执行成功"
except Exception as e:
tasks_db[task_id].status = "failed"
tasks_db[task_id].result = f"任务失败: {str(e)}"
tasks_db[task_id].completed_at = datetime.now()
@app.post("/tasks", response_model=Task)
async def create_task(name: str, background_tasks: BackgroundTasks):
task_id = str(uuid.uuid4())
task = Task(
id=task_id,
name=name,
status="pending",
created_at=datetime.now()
)
tasks_db[task_id] = task
# 在后台执行任务
background_tasks.add_task(execute_long_running_task, task_id, name)
return task
@app.get("/tasks/{task_id}", response_model=Task)
async def get_task(task_id: str):
if task_id not in tasks_db:
return {"error": "任务不存在"}
return tasks_db[task_id]
@app.get("/tasks", response_model=List[Task])
async def list_tasks():
return list(tasks_db.values())
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
总结
Python的异步编程通过asyncio库提供了强大的并发处理能力,而FastAPI框架在此基础上构建了现代化的Web开发体验。掌握异步编程不仅能够提升应用性能,还能更好地应对高并发场景。
关键要点回顾:
- 理解事件循环和协程的工作原理
- 熟练使用async/await语法
- 掌握Task、Queue、Semaphore等高级特性
- 在FastAPI中合理应用异步编程模式
- 遵循异步编程的最佳实践
参考文献
-
Python官方文档 - asyncio模块 https://docs.python.org/3/library/asyncio.html
-
FastAPI官方文档 https://fastapi.tiangolo.com/
-
《Python异步编程实战》- 人民邮电出版社
-
SQLAlchemy异步支持文档 https://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.html
-
Uvicorn官方文档 https://www.uvicorn.org/
通过本文的学习,您应该已经掌握了Python异步编程的核心概念和FastAPI框架的实战应用。在实际开发中,建议根据具体业务场景选择合适的异步模式,并持续优化性能。

1236

被折叠的 条评论
为什么被折叠?



