Files
person-share/python_rules_3_12.md
T

306 lines
12 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.
## Python 规范
### 依赖管理
- **使用 uv 管理依赖**
```bash
uv init --python 3.12 .
uv add <package_name>
...
uv sync
uv lock # 锁定确切版本
```
- **明确区分生产依赖和开发依赖**
- 生产依赖:`uv add <package_name>`
- 开发依赖(测试、构建、静态检查等):`uv add --dev <package_name>`
- **明确版本约束**
- 在 `pyproject.toml` 中使用语义化版本约束,避免因依赖库大版本更新(如
Pydantic V1 -> V2)导致的不兼容问题。
- 示例:`pydantic>=2.0,<3.0`
- **补充类型存根**
- 对于不自带类型定义的第三方库,必须添加对应的 `types-*` 包以支持静态类型检查
- 示例:`uv add types-requests types-pytz`
### 代码规则
- **显式声明类型**
- 方法参数、属性、返回值等必须显式声明类型。
- 禁止使用 `Dict` 传递非结构化的参数、返回值或数据对象,应使用 `dataclass` 或
`Pydantic` 模型。
```python
from pydantic import BaseModel, field_validator
class Config(BaseModel):
min_poll_interval: int = 5
max_poll_interval: int = 1800
@field_validator('max_poll_interval')
@classmethod
def validate_max_greater_than_min(cls, v, info):
if 'min_poll_interval' in info.data and v <= info.data['min_poll_interval']:
raise ValueError('max_poll_interval must be greater than min_poll_interval')
return v
```
- **用绝对导入**
- 使用绝对导入,而不是相对导入。
- 绝对导入的优点是:更清晰,更容易理解。
- **运行时数据验证**
- 充分利用 Pydantic 的验证器(`@field_validator`)对配置、API 输入等进行严格的
运行时检查,提前防止数据错误。
- **构造函数初始化**
- 实例必须的初始化工作应当在 `__init__` 构造函数里完成,而不是让调用者额外调用
“init” 方法。
- **遵循 PEP 8**
- 使用 Black + Ruff/isort 自动格式化和检查。
- 最大行宽不超过 88(Black 默认)或团队约定值。
- **命名规范**
- 模块、变量、函数:`snake_case`
- 类名、异常名:`PascalCase`
- 常量:`UPPER_SNAKE_CASE`
- 内部方法/函数 名字需要以 _ 开头
- **文档与注释**
- 每个模块、类、函数都要有 docstring,遵循 Google 样式。
- 在复杂逻辑处添加必要注释,解释“为什么”这么做,而不是“做了什么”。
### 接口与抽象
- **合理使用 `typing.Protocol`**
- **价值**:在策略和插件化场景下,用协议定义契约比显式继承更灵活,既保持了低耦
合,又兼顾了 IDE 智能补全和 Mypy 校验。
- **建议**:对外暴露的接口优先使用 `Protocol`,内部默认实现再继承或注册。
### 配置管理
- **引入 `pydantic-settings` 统一配置**
- **价值**:把 `.env`、环境变量、CLI 参数统一为 Pydantic 模型,避免项目里到处
零散地调用 `os.getenv`,提高了配置的可追溯性和类型安全。
- **建议**:新建一个 `Settings` 类集中管理,配合 `uv add pydantic-settings` 并
在 `uv.sync` 后自动生成对应代码片段。
### 日志管理
- **结构化日志 (structlog + JSON sink)**
- **价值**:标准化日志字段(`timestamp`、`level`、`event`、`trace_id`…),与
ELK/Loki/ClickHouse 等分析平台无缝集成,提升故障定位与监控能力。
- **建议**:从项目骨架开始引入,定义公共 `Logger` 配置,并在 CI 或部署文档中说
明如何在生产环境启动 JSON 输出。
### 安全规范
- **输入验证与净化**
- 所有外部输入(API 请求、配置文件、用户上传内容等)都必须通过 Pydantic 模型进
行严格的验证和类型转换。
- **敏感数据处理**
- 禁止在日志中明文记录密码、API Key 等敏感信息。
- 使用 `pydantic-settings` 等工具从环境变量或安全的 Secret 管理服务中加载敏感
配置。
- **依赖库安全性检查**
- 定期使用 `uv audit` 或 `pip-audit` 扫描项目依赖,及时发现并修复已知的安全漏
洞。
- 在 CI 流程中集成依赖扫描步骤。
### 测试最佳实践
- **测试行为而非实现**
- 单元测试应验证公共接口的业务逻辑和行为,而不是其内部实现细节。
- **隔离测试单元**
- 必须 Mock 所有外部依赖(如 API 调用、数据库、文件系统),确保测试的独立性和
稳定性。
- **集成测试策略**
- 编写集成测试来验证关键模块间的交互,例如服务与数据库的连接。
- 使用测试容器(Testcontainers)或 Docker Compose 为集成测试提供隔离的、真实的
依赖服务。
- **性能测试**
- 对性能敏感的关键路径,使用 `pytest-benchmark` 等工具编写基准测试,防止性能回
退。
- **测试数据管理**
- 使用 `Faker` 等库生成隔离且可复现的测试数据。
- 严禁在测试中使用生产环境数据。
- **处理无头环境中的 GUI 依赖**
- 在无头(HeadlessCI/CD 环境中,若项目依赖 GUI 库(如 `pyautogui`),会导致
`DISPLAY` 环境变量缺失错误。
- **解决方案**:在 `tests/conftest.py` 中提前 Mock 相关的 GUI 模块。
```python
# tests/conftest.py
import sys
from unittest.mock import MagicMock
# 在导入测试用例前Mock GUI相关模块
sys.modules['pyautogui'] = MagicMock()
sys.modules['pygetwindow'] = MagicMock()
```
- **编写健壮的测试**
- 测试用例应具备健壮性,不应依赖具体的、可能变化的实现细节(如时区缩写 "CST"
vs "LMT")。应测试其核心逻辑。
- 使用参数化测试(`@pytest.mark.parametrize`)覆盖边界条件和异常情况。
### 异常处理最佳实践
1. **捕获具体异常**
避免使用 `except Exception:` 或裸 `except:`,应捕获特定异常。
2. **记录日志而非打印**
在 `except` 块中使用 `logging` 模块记录异常信息(包括堆栈跟踪)。
3. **定义自定义异常类**
针对业务领域定义专用异常类,使错误类型更加语义化。
4. **利用 `else` 与 `finally`**
- `else`:用于“正常流程”代码。
- `finally`:用于资源清理,确保总能执行。
5. **让意外异常继续冒泡**
只处理预期内的异常,不隐藏未知错误。
6. **结合上下文管理器**
优先使用 `with` 语句管理资源,自动处理异常和清理。
### 性能优化指南
- **内存使用优化**
- 优先使用生成器(`yield`)处理大型数据集,避免一次性加载到内存。
- 对固定且属性较多的对象使用 `__slots__` 来减少内存占用。
- **并发/异步编程**
- 对 I/O 密集型任务,优先使用 `asyncio` 和 `async/await` 提高并发能力。
- 避免在异步代码中调用阻塞的 I/O 操作。
- **大数据处理**
- 在处理大型表格数据时,考虑使用 `Polars` 等高性能库。
- 数据处理应以流式(Streaming)或分块(Chunking)方式进行。
### 静态类型检查
- 使用 **Mypy**(或 **Pyright**)在 CI 中强制执行类型检查。
```bash
mypy .
```
- 推荐启用 `--strict` 模式,或根据团队情况定制 `pyproject.toml` 中的
`[tool.mypy]` 配置。
- **全面开启 Ruff**
- **价值**:在 PEP 8 之外,再覆盖现代化升级提示(UP\*)、常见 Bug(B/BLE)、安
全隐患(S)等规则,一次性收割多类质量红利。
- **建议**:在 `pyproject.toml` 中启用最全的 `select` 集合,CI 里把 Ruff 报错
作为门禁。
### 项目文档与知识沉淀
- **记录已知“坑点”**
- 在项目 `CLAUDE.md` 或 `README.md` 中,必须建立一个专门区域,记录开发过程中遇
到的特有问题、环境陷阱和解决方案。
- **示例记录**
> #### 项目特有的异常行为或警告
>
> 1. **GUI 依赖问题**: 在无头环境测试需要 Mock `pyautogui`。
> 2. **时区格式化**: `pytz` 库对北京时区的缩写可能返回 `LMT` 而非 `CST`,测
> 试时需灵活判断。
- **提供环境配置文档**
- 为新成员准备清晰的环境配置指南,包括必要的环境变量和工具链。
### 环境与工作流
- 在项目根目录提供 `Makefile` 或 `pyproject.toml [project.scripts]` 封装常用命令
```toml
# pyproject.toml
[project.scripts]
lint = "ruff check . --fix"
format = "black ."
test = "pytest --cov=src"
check = "mypy ."
```
- **使用 pre-commit Hooks**
- 强烈建议配置 pre-commit,在代码提交前自动执行格式化和静态检查,保证代码质量
### 团队协作与发布流程
- **代码审查清单**
- 在项目中创建 `PULL_REQUEST_TEMPLATE.md`,提供一个清单,确保审查点(如测试覆
盖、文档更新、遵循规范)不被遗漏。
- **版本管理策略**
- 遵循语义化版本(SemVer)规范(主版本.次版本.修订号)。
- 使用 Git 标签(`git tag`)标记每个正式发布版本。
- **发布流程**
- 推荐使用 CI/CD 流水线自动化测试、构建和发布流程。
### 语言限制
- **禁止在运行时变更对象布局**
- 所有类必须声明 `__slots__` 或使用冻结(immutable)数据类,从根本上禁用动态增
删属性。
```python
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class Point:
x: float
y: float
# 使用 frozen=True 和 slots=True 同时获得不可变性和性能优化
# 任何修改属性或添加新属性的操作都会抛出异常
```
- **「禁止 Any」与「全员 frozen + slots」**
- **价值**:极大提升类型检查严格度和运行时内存/访问性能,并防止动态增删属性引
发的隐蔽 Bug。
- **建议**:主业务代码强制执行,测试代码,实验性或 PoC 模块可在 `mypy.ini` 中
针对性豁免;同时在代码审查中重点关注。
```toml
[mypy]
disallow_untyped_defs = True # 所有函数/方法必须有类型注释
disallow_any_unimported = True # 禁止隐式 Any(未导入类型)
disallow_any_explicit = True # 禁止显式 Any
warn_unused_ignores = True
no_implicit_optional = True
[mypy-poc.*] # 实验性或 PoC 模块
disallow_untyped_defs = False
disallow_any_explicit = False
[mypy-tests.*]
disallow_untyped_defs = False
disallow_any_explicit = False
```
- **谨慎使用运算符重载**
- **原则**:仅在能显著提高代码可读性和表达力时才使用运算符重载,避免滥用。
- **适用场景**:主要用于数学计算(如向量、矩阵)、数据分析或构建领域特定语言(
DSL)等,此时重载能让代码更自然、更符合领域习惯。
- **禁止场景**:避免在通用业务对象上重载运算符,这会降低代码的清晰度和可维护性
```python
# ✅ 推荐:在数学/几何领域,重载使代码更直观
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
# ❌ 不推荐:在业务对象上重载,含义模糊
class ShoppingCart:
def __add__(self, item): ... # 含义不清晰,应使用 .add_item(item)
```
### 信号处理与优雅关闭
- 使用 `signal.signal()` 注册 `SIGTERM`/`SIGINT` 处理函数,收到信号后停止接收新任务,优雅退出。
- 在 `try...finally` 中确保调用子进程或线程的 `join()`/`close()`,避免僵尸进程或资源泄漏。
### 测试与调试
- `pytest` 命令加上 `-s --durations=0 --log-cli-level=INFO`,保证子进程日志和耗时信息完整输出。