# Python后端

## 规则（Rules）

# Python后端开发规范

## 适用对象和范围

本规范适用于所有使用Python进行Web后端开发的场景，包括FastAPI/Django/Flask框架搭建、API实现和业务逻辑编写。

---

## 1. 缩进规范

**规则**：统一使用4个空格缩进，遵循PEP8规范。

- ✅ 正确：每级缩进4个空格
- ❌ 错误：使用Tab或2空格

**违反后果**：Python依赖缩进定义代码块，缩进不一致会导致语法错误。

---

## 2. 行宽规范

**规则**：每行代码不超过79个字符（PEP8标准）。

- ✅ 正确：长表达式使用括号换行或反斜杠
- ❌ 错误：一行超过79字符

**违反后果**：超过行宽导致代码在终端和代码审查工具中显示不完整。

---

## 3. 命名规范

**规则**：类名使用PascalCase，函数和变量名使用snake_case，常量名使用SCREAMING_SNAKE_CASE。

| 标识符类型 | 命名法 | 示例 |
|-----------|--------|------|
| 类名 | PascalCase | `class UserService:` |
| 函数名 | snake_case | `def get_user_data():` |
| 变量名 | snake_case | `user_name = '张三'` |
| 常量名 | SCREAMING_SNAKE_CASE | `MAX_RETRY_COUNT = 3` |

- ✅ 正确：`class UserService:`、`def get_user_data():`
- ❌ 错误：`class user_service:`、`def GetUserData():`

**违反后果**：命名不符合PEP8规范导致代码审查不通过，社区风格不一致。

---

## 4. 注释规范

**规则**：函数和类必须使用docstring格式注释。

```python
def get_user_data(user_id: int) -> dict:
    """获取用户数据
    
    Args:
        user_id: 用户ID
        
    Returns:
        用户数据字典
        
    Raises:
        ValueError: 用户不存在时
    """
    pass
```

- ✅ 正确：函数有docstring注释
- ❌ 错误：函数无注释或只写 `# 获取用户数据`

**违反后果**：缺少docstring导致IDE无法提供类型提示和文档生成。

---

## 5. 类型注解规范

**规则**：函数参数和返回值必须使用类型注解。

- ✅ 正确：`def get_user(user_id: int) -> dict:`
- ❌ 错误：`def get_user(user_id):`

**违反后果**：缺少类型注解导致代码可读性差，无法利用静态类型检查工具。

---

## 6. 异常处理规范

**规则**：必须使用try/except捕获异常，禁止使用裸except。

- ✅ 正确：
```python
try:
    result = await db.execute(query)
except ValueError as e:
    logger.error(f"参数错误: {e}")
    raise
```

- ❌ 错误：
```python
try:
    result = await db.execute(query)
except:  # 裸except
    pass
```

**违反后果**：裸except会捕获所有异常（包括KeyboardInterrupt），可能导致程序无法正常退出。

---

## 7. 敏感信息安全规范

**规则**：禁止将密码、密钥硬编码在代码中，必须使用环境变量或配置文件。

- ✅ 正确：`DB_PASSWORD = os.getenv('DB_PASSWORD')`
- ❌ 错误：`DB_PASSWORD = '123456'`

**违反后果**：硬编码敏感信息存在严重安全风险。

## 方法（Methods）

# Python后端开发方法

## 前置条件

- [ ] 已获取需求文档和API设计文档
- [ ] 已确定技术栈（FastAPI/Django/Flask）
- [ ] 已了解数据模型定义

## 流程概览

分析需求 → 初始化项目 → 编写数据模型 → 编写API接口 → 编写配置和启动文件

## 详细步骤

### 步骤1：分析需求
分析需求文档和API设计文档，确定技术栈（FastAPI/Django/Flask）和数据模型。

### 步骤2：初始化项目
创建项目目录结构。

## 技巧（Tips）

# Python后端开发技巧

## 1. 使用Pydantic模型做参数校验（FastAPI）

**适用场景**：使用FastAPI框架时，需要自动校验请求参数。

**具体做法**：定义Pydantic模型作为请求体的类型注解。

**对比说明**：

| 维度 | 手动校验 | Pydantic自动校验 |
|------|---------|----------------|
| 代码量 | 每个字段写if判断 | 声明式模型定义 |
| 错误信息 | 需手动返回 | 自动生成清晰错误信息 |
| 类型转换 | 需手动转换 | 自动类型转换 |

**示例**：
```python
from pydantic import BaseModel, EmailStr

class CreateUserRequest(BaseModel):
    name: str
    email: EmailStr
    age: int = 18  # 默认值

@app.post("/users")
async def create_user(req: CreateUserRequest):
    # req 已经过自动校验
    return {"name": req.name, "email": req.email}
```

**注意事项**：Pydantic v2 性能更好，推荐使用。

---

## 2. 使用异步数据库驱动

**适用场景**：需要处理高并发IO操作时。

**具体做法**：使用异步数据库驱动（如 `databases`、`asyncpg`、`aiomysql`）配合 `async/await`。

**对比说明**：

| 维度 | 同步驱动 | 异步驱动 |
|------|---------|---------|
| 并发性能 | 阻塞等待IO | 等待IO时处理其他请求 |
| 代码风格 | 同步代码 | async/await |
| 框架兼容 | 需额外配置线程池 | FastAPI原生支持 |

**示例**：
```python
from databases import Database

database = Database('postgresql://user:pass@localhost/db')

@app.on_event("startup")
async def startup():
    await database.connect()

@app.get("/users")
async def get_users():
    query = "SELECT * FROM users"
    return await database.fetch_all(query)
```

**注意事项**：异步驱动需要数据库连接池支持，且ORM（如SQLAlchemy）需要异步版本。

---

## 3. 使用依赖注入管理共享资源

**适用场景**：需要共享数据库连接、配置等资源时。

**具体做法**：使用FastAPI的 `Depends` 或Flask的依赖注入扩展。

**示例**：
```python
# FastAPI依赖注入
from fastapi import Depends, FastAPI

app = FastAPI()

async def get_db():
    db = Database()
    try:
        await db.connect()
        yield db
    finally:
        await db.disconnect()

@app.get("/users")
async def get_users(db = Depends(get_db)):
    return await db.fetch_all("SELECT * FROM users")
```

**注意事项**：依赖注入的生命周期管理很重要，确保资源正确释放。

---

## 4. 常见问题速查

| 问题 | 原因 | 解决方案 |
|------|------|---------|
| 模块导入失败 | 路径问题或循环导入 | 检查 `sys.path` 和导入顺序，使用延迟导入 |
| 跨域错误 | 前后端域名不一致 | 使用 `CORSMiddleware` 配置允许的origin |
| 数据库连接泄漏 | 未关闭连接 | 使用上下文管理器或依赖注入自动管理 |
| 异步函数同步调用报错 | 在同步代码中调用了async函数 | 使用 `asyncio.run()` 或在async函数中调用 |
| requirements版本冲突 | 依赖版本不兼容 | 使用 `pip-compile` 管理依赖版本 |
