Files
jdy_fastapi/FASTAPI_LEARNING.md
T
2025-11-07 17:48:49 +08:00

711 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FastAPI 学习文档
## 📚 目录
1. [FastAPI 简介](#fastapi-简介)
2. [Flask vs FastAPI 对比](#flask-vs-fastapi-对比)
3. [FastAPI 核心概念](#fastapi-核心概念)
4. [项目中的 FastAPI 使用](#项目中的-fastapi-使用)
5. [学习路径建议](#学习路径建议)
6. [常见问题解答](#常见问题解答)
---
## FastAPI 简介
### 什么是 FastAPI
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,基于 Python 3.6+ 的类型提示(type hints)。
### 主要特点
1. **高性能**:与 NodeJS 和 Go 相当,是最快的 Python 框架之一
2. **快速开发**:开发速度提升约 200% 到 300%
3. **自动文档**:自动生成交互式 API 文档(Swagger UI
4. **类型提示**:基于 Python 类型提示,提供更好的 IDE 支持
5. **异步支持**:原生支持 async/await
6. **数据验证**:自动进行请求和响应数据验证
---
## Flask vs FastAPI 对比
### 1. 基本语法对比
#### Flask 写法
```python
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
return jsonify({'msg': 'success'})
```
#### FastAPI 写法
```python
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel
app = FastAPI()
class RequestData(BaseModel):
name: str
age: int
@app.post("/webhook")
async def webhook(data: RequestData):
return JSONResponse({'msg': 'success'})
```
### 2. 主要区别
| 特性 | Flask | FastAPI |
|------|-------|---------|
| **异步支持** | 需要额外库(Flask-AsyncIO | 原生支持 async/await |
| **类型验证** | 手动验证 | 自动验证(基于 Pydantic |
| **API 文档** | 需要手动编写 | 自动生成(Swagger/OpenAPI |
| **性能** | 中等 | 高性能(接近 NodeJS |
| **依赖注入** | 需要额外库 | 内置支持 |
| **数据验证** | 手动处理 | 自动验证和转换 |
### 3. 请求处理对比
#### Flask
```python
from flask import request
@app.route('/api', methods=['POST'])
def api():
# 手动获取 JSON 数据
data = request.get_json()
# 手动验证
if not data or 'name' not in data:
return jsonify({'error': '缺少 name 字段'}), 400
return jsonify({'result': data['name']})
```
#### FastAPI
```python
from pydantic import BaseModel
class Item(BaseModel):
name: str
age: int
@app.post("/api")
async def api(item: Item):
# 自动验证,如果 name 缺失会自动返回 422 错误
return {'result': item.name}
```
---
## FastAPI 核心概念
### 1. 应用实例(FastAPI App
```python
from fastapi import FastAPI
# 创建 FastAPI 应用实例
app = FastAPI(
title="简道云FastAPI服务", # API 文档标题
description="简道云 API 服务", # API 描述
version="1.0.0" # 版本号
)
```
**项目中的使用**`main.py`):
```python
app = FastAPI(title="简道云FastAPI服务")
```
### 2. 路由装饰器(Route Decorators
FastAPI 使用装饰器定义路由,类似于 Flask:
```python
@app.get("/") # GET 请求
@app.post("/") # POST 请求
@app.put("/") # PUT 请求
@app.delete("/") # DELETE 请求
```
**项目中的使用**`main.py`):
```python
@app.post("/webhook")
async def webhook(request: Request):
# 处理逻辑
pass
```
### 3. 请求对象(Request
FastAPI 的 `Request` 对象提供了访问请求信息的方法:
```python
from fastapi import Request
@app.post("/webhook")
async def webhook(request: Request):
# 获取 JSON 数据
data = await request.json()
# 获取请求头
headers = request.headers
# 获取查询参数
query_params = request.query_params
# 获取路径参数
path_params = request.path_params
```
**项目中的使用**`main.py`):
```python
@app.post("/webhook")
async def webhook(request: Request):
# 获取请求数据
data = await request.json()
header = request.headers
# 解码请求头
decoded_header = app_tools.decode_headers(header)
```
### 4. 响应对象(Response
FastAPI 提供了多种响应类型:
```python
from fastapi.responses import JSONResponse, HTMLResponse, PlainTextResponse
@app.post("/api")
async def api():
# JSON 响应
return JSONResponse({'msg': 'success'})
# 或者直接返回字典(FastAPI 会自动转换为 JSON
return {'msg': 'success'}
```
**项目中的使用**`main.py`):
```python
return JSONResponse(result)
```
### 5. 异步函数(Async Functions
FastAPI 支持异步函数,使用 `async``await`
```python
@app.post("/webhook")
async def webhook(request: Request):
# 异步获取 JSON 数据
data = await request.json()
# 异步调用其他函数
result = await some_async_function(data)
return result
```
**项目中的使用**`main.py`):
```python
@app.post("/webhook")
async def webhook(request: Request):
data = await request.json() # 异步获取数据
# ...
result = await anyio.to_thread.run_sync(response_queue.get) # 异步执行同步函数
```
### 6. 生命周期事件(Lifecycle Events
FastAPI 提供了应用启动和关闭事件:
```python
@app.on_event("startup")
async def startup_event():
"""应用启动时执行"""
print("应用启动")
@app.on_event("shutdown")
async def shutdown_event():
"""应用关闭时执行"""
print("应用关闭")
```
**项目中的使用**`main.py`):
```python
@app.on_event("startup")
def on_startup():
"""应用启动时初始化"""
app.state.app_tools = AppTools(Config)
app.state.logger = setup_global_logger(Config)
app.state.f6_module = F6Module()
app.state.f6_plugin_module = F6PluginModule()
app.state.other_module = OtherPluginModule()
```
### 7. 应用状态(Application State
FastAPI 允许在应用实例上存储状态:
```python
# 设置状态
app.state.my_data = "some value"
# 获取状态
my_data = app.state.my_data
```
**项目中的使用**`main.py`):
```python
# 在启动时设置
app.state.app_tools = AppTools(Config)
app.state.logger = setup_global_logger(Config)
# 在路由中使用
logger = app.state.logger
app_tools: AppTools = app.state.app_tools
```
### 8. 数据验证(Pydantic Models
FastAPI 使用 Pydantic 进行数据验证:
```python
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
email: str = None # 可选字段
@app.post("/users")
async def create_user(user: User):
# user 已经自动验证和转换
return {"name": user.name, "age": user.age}
```
**项目中的潜在使用**(可以改进):
```python
# 可以定义请求模型
class WebhookRequest(BaseModel):
api_key: str
entry_id: str
data_id: str
Action: str = None # 可选字段
@app.post("/webhook")
async def webhook(request: Request, data: WebhookRequest):
# data 已经自动验证
pass
```
---
## 项目中的 FastAPI 使用
### 1. 项目结构分析
```
fastapi_app/
├── main.py # FastAPI 应用入口
├── api.py # API 工具类(简道云 API 封装)
├── app/
│ ├── api.py # API 模块(简道云 API 封装)
│ ├── config.py # 配置管理
│ ├── module/ # 业务模块
│ ├── tasks/ # 后台任务
│ └── utils/ # 工具函数
└── requirements.txt # 依赖列表
```
### 2. main.py 详解
让我们逐步分析 `main.py` 文件:
#### 2.1 导入和初始化
```python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import json
import anyio
from app.utils.app_tools import AppTools, setup_global_logger
from app.module.F6_Plugin_module import F6PluginModule
from app.module.module import F6Module
from app.module.other_module import OtherPluginModule
from app.config import Config
# 创建 FastAPI 应用实例
app = FastAPI(title="简道云FastAPI服务")
```
**说明**
- `FastAPI`:主应用类
- `Request`:请求对象,用于访问请求信息
- `JSONResponse`JSON 响应类
#### 2.2 启动事件
```python
@app.on_event("startup")
def on_startup():
"""应用启动时初始化"""
app.state.app_tools = AppTools(Config)
app.state.logger = setup_global_logger(Config)
app.state.f6_module = F6Module()
app.state.f6_plugin_module = F6PluginModule()
app.state.other_module = OtherPluginModule()
```
**说明**
- `@app.on_event("startup")`:应用启动时执行
- `app.state`:存储应用级别的状态
- 初始化工具类、日志记录器和业务模块
#### 2.3 路由处理
```python
@app.post("/webhook")
async def webhook(request: Request):
"""
接受前端请求后将任务放入消息队列
Returns:
any: 返回任务处理的结果
"""
logger = app.state.logger
app_tools: AppTools = app.state.app_tools
# 获取请求数据
data = await request.json()
header = request.headers
# 解码请求头
decoded_header = app_tools.decode_headers(header)
# 获取操作映射表
action_map = get_action_map()
action = decoded_header.get('Action')
# 处理逻辑...
# 将任务放入消息队列
response_queue = app_tools.enqueue_task(handler, data)
# 等待任务处理结果
result = await anyio.to_thread.run_sync(response_queue.get)
logger.info(json.dumps(result, ensure_ascii=False, indent=4))
return JSONResponse(result)
```
**关键点**
1. `async def`:异步函数定义
2. `await request.json()`:异步获取 JSON 数据
3. `await anyio.to_thread.run_sync()`:在线程池中执行同步函数
4. `JSONResponse`:返回 JSON 响应
### 3. 任务队列机制
项目使用自定义的任务队列来处理请求:
```python
# 在 app_tools.py 中
class AppTools:
def __init__(self, config):
self.task_queue = Queue()
self._start_task_thread()
def enqueue_task(self, handler, data):
response_queue = Queue()
self.task_queue.put({
'handler': handler,
'data': data,
'response': response_queue
})
return response_queue
```
**工作流程**
1. 请求到达 `/webhook` 端点
2. 将任务放入队列
3. 后台线程处理任务
4. 等待结果返回
### 4. 操作映射机制
项目使用操作映射表来路由不同的操作:
```python
def get_action_map() -> dict:
"""获取操作映射表"""
f6_module = app.state.f6_module
f6_plugin_module = app.state.f6_plugin_module
other_module = app.state.other_module
return {
'login_in': f6_module.accept_login_message,
'get_company_information': f6_module.get_company_information,
'create_brand': f6_plugin_module.create_brand,
# ... 更多操作
}
```
**说明**
- 通过请求头中的 `Action` 字段确定要执行的操作
- 使用字典映射操作名到处理函数
---
## 学习路径建议
### 阶段 1:基础理解(1-2 天)
1. **理解 FastAPI 基本概念**
- 阅读官方文档:https://fastapi.tiangolo.com/
- 理解路由、请求、响应的基本用法
2. **运行项目**
```bash
# 安装依赖
pip install -r requirements.txt
# 运行项目
python main.py
# 或
uvicorn main:app --reload
```
3. **访问 API 文档**
- 启动后访问:http://localhost:5003/docs
- 查看自动生成的 Swagger UI 文档
### 阶段 2:代码分析(2-3 天)
1. **分析 main.py**
- 理解应用初始化流程
- 理解路由处理逻辑
- 理解任务队列机制
2. **分析业务模块**
- 查看 `app/module/` 目录下的模块
- 理解操作映射机制
- 理解模块间的交互
3. **分析工具类**
- 查看 `app/utils/app_tools.py`
- 理解任务队列实现
- 理解日志记录机制
### 阶段 3:实践练习(3-5 天)
1. **添加新路由**
```python
@app.get("/health")
async def health_check():
return {"status": "ok"}
```
2. **添加数据验证**
```python
from pydantic import BaseModel
class WebhookData(BaseModel):
api_key: str
entry_id: str
data_id: str
@app.post("/webhook")
async def webhook(data: WebhookData):
return {"received": data.dict()}
```
3. **添加错误处理**
```python
from fastapi import HTTPException
@app.post("/webhook")
async def webhook(request: Request):
try:
data = await request.json()
# 处理逻辑
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
```
### 阶段 4:深入学习(1-2 周)
1. **学习异步编程**
- 理解 `async/await`
- 理解 `asyncio`
- 理解并发处理
2. **学习 Pydantic**
- 数据验证
- 数据序列化
- 自定义验证器
3. **学习依赖注入**
- FastAPI 的依赖注入系统
- 数据库连接管理
- 认证和授权
---
## 常见问题解答
### Q1: FastAPI 和 Flask 的主要区别是什么?
**A:** 主要区别:
1. **性能**FastAPI 性能更高,支持异步
2. **类型验证**FastAPI 自动验证,Flask 需要手动
3. **API 文档**FastAPI 自动生成,Flask 需要手动编写
4. **异步支持**FastAPI 原生支持,Flask 需要额外库
### Q2: 为什么使用 `async def` 而不是 `def`
**A:**
- `async def` 允许使用 `await` 关键字
- 可以异步处理 I/O 操作(如网络请求、数据库查询)
- 提高并发性能
**示例**
```python
# 同步(阻塞)
def sync_function():
data = requests.get("https://api.example.com") # 阻塞
return data
# 异步(非阻塞)
async def async_function():
async with httpx.AsyncClient() as client:
data = await client.get("https://api.example.com") # 非阻塞
return data
```
### Q3: `app.state` 是什么?为什么要用它?
**A:**
- `app.state` 是 FastAPI 提供的应用级状态存储
- 用于存储需要在多个路由之间共享的数据
- 类似于 Flask 的 `g` 对象,但作用域是整个应用
**项目中的使用**
```python
# 启动时设置
app.state.logger = setup_global_logger(Config)
# 在路由中使用
logger = app.state.logger
```
### Q4: 如何处理同步函数?
**A:**
使用 `anyio.to_thread.run_sync()` 在线程池中执行同步函数:
```python
import anyio
# 同步函数
def sync_function(data):
# 耗时操作
return result
# 在异步函数中调用
@app.post("/api")
async def api(request: Request):
result = await anyio.to_thread.run_sync(sync_function, data)
return result
```
### Q5: 如何添加中间件?
**A:**
使用 `@app.middleware()` 装饰器:
```python
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
```
### Q6: 如何添加 CORS 支持?
**A:**
使用 `CORSMiddleware`
```python
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许所有源
allow_credentials=True,
allow_methods=["*"], # 允许所有方法
allow_headers=["*"], # 允许所有头
)
```
### Q7: 如何添加认证?
**A:**
使用依赖注入:
```python
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer
security = HTTPBearer()
async def verify_token(token: str = Depends(security)):
if token != "valid_token":
raise HTTPException(status_code=401, detail="Invalid token")
return token
@app.post("/api")
async def api(token: str = Depends(verify_token)):
return {"message": "Authenticated"}
```
---
## 推荐资源
1. **官方文档**https://fastapi.tiangolo.com/
2. **中文文档**https://fastapi.tiangolo.com/zh/
3. **Pydantic 文档**https://docs.pydantic.dev/
4. **Uvicorn 文档**https://www.uvicorn.org/
---
## 总结
FastAPI 是一个现代、高性能的 Web 框架,特别适合构建 API。相比 Flask,它提供了:
1. **更好的性能**:异步支持,高性能
2. **自动验证**:基于类型提示的自动数据验证
3. **自动文档**:自动生成 API 文档
4. **更好的开发体验**:类型提示、IDE 支持
通过这个项目,你可以学习到:
- FastAPI 的基本用法
- 异步编程
- 任务队列机制
- 模块化架构设计
建议按照学习路径逐步深入,多实践、多思考,逐步掌握 FastAPI 的精髓。