用途
这套规范用于统一 Python 3.11+ 项目的开发实践,覆盖类型安全、架构设计、错误处理与安全、性能、命名、脚本依赖、UI/CLI、测试与文档、工具链等主题。它被定位为“新 Python 工作的强默认值”,而不是要求重构一个已经自洽的既有项目。
适用性与优先级
规范明确给出约束顺序:用户明确要求与安全/安全约束优先;其次是目标仓库支持的 Python 版本、公开契约、架构、依赖、CI、格式化/检查/类型检查配置与既有本地约定;再次是框架/库生态惯例;最后才是本插件默认值。不得仅为满足默认规则而引入依赖、抽象、架构层、兼容性变更或大范围现代化改造。当既有实践自洽且安全时予以保留;当它与正确性、安全、明确要求或自身声明的契约冲突时,应指出冲突并做最小必要修改。每次变更都应保留无关行为与 API,只修改需求与受影响契约所需的部分。
类型安全与现代模式
使用 Python 3.11+ 原生类型提示(list[str]、dict[str, int]、str | None),替代 List、Dict、Optional、Union 等旧式 typing 导入。对 Any 采取边界策略:优先精确类型,把 Any、宽泛 object 与未检查的 cast() 限制在明确的动态或外部边界,并尽快转换为更强的内部类型;当第三方 API、插件协议、装饰器或刻意动态的接口无法准确表达时,窄范围且有理由的 Any 优于不诚实或过度复杂的类型标注。策略例外应按文件局部化:把确实需要例外的 ingest/parser/adapter 方法或类放入专用边界模块,并为该文件配置检查器例外,不要把内联抑制散落到强类型模块中。数据结构方面,当运行时校验/序列化对边界或面向智能体的 JSON 契约有实质收益时优先 Pydantic BaseModel;内部值对象优先 dataclass;无需运行时校验的类型化映射形状用 TypedDict。鸭子类型优先用 typing.Protocol 做结构化子类型。类型收窄用 TypeIs(PEP 742,Python 3.13+),仅在面向 Python < 3.13 且无 typing_extensions 时用 TypeGuard。可读性更好时使用海象运算符与 match-case。类型检查默认用 ty(Astral),命令为 uv run ty check;应从 .pre-commit-config.yaml 再到 CI 检测实际使用的检查器,而不是只看配置表。解析 TOML 用 tomlkit(保留格式与注释),仅标准库脚本用 tomllib;解析 Markdown 走 marko AST,不用正则解析器。版本特性需对照项目 requires-python 下限与各版本补充说明。版本生命周期(来源:https://devguide.python.org/versions,访问于 2026-03-23):3.10 EOL 2026-10,3.11 安全维护至 2027-10,3.12 安全维护至 2028-10,3.13 缺陷修复至 2029-10,3.14 缺陷修复至 2030-10;选择 requires-python 下限时优先仍处于缺陷修复状态的版本。
架构与设计
按变化原因分离关注点。CLI 应用的有用默认是 CLI → 核心逻辑 → 服务 → 输出边界;不要制造没有独立职责的层。多个消费者需要的共享领域模型/常量/异常放在明显稳定的模块中,不要仅为满足模式而创建 shared/ 目录。依赖注入优先直接参数;当存在多实现、外部服务、测试接缝或架构隔离理由时再引入 Protocol 边界。SOLID 作为设计压力,指向内聚职责、显式依赖、可替换契约与小接口,不要仅为展示原则而增加间接层。构造在清晰时优先直接构造;当构造策略复杂、重复、有条件或需要隔离时引入工厂/构建器。模块卫生:Python 源文件默认控制在约 500 物理行以内(含 docstring,因为它同样消耗读者/智能体上下文);接近或超过约 500 行需要主动做分解分析,优先按内聚职责拆分。长函数、深嵌套、循环导入、膨胀的公开接口同样触发设计评审。代码异味应作为设计信号追查其成因,而不是压制。
错误处理与安全
Fail-fast:只在有具体恢复动作或需要添加上下文时捕获异常,其余向上传播;禁止裸 except: 或静默吞掉异常。示例中仅对 ConnectionError 做特定恢复(记录警告并回退缓存)。重新抛出时用 e.add_note() 或 raise ... from e 添加上下文。安全方面:防止 SQL 注入(参数化查询)、防止命令注入(不要对用户输入使用 shell=True)、校验所有外部输入、绝不硬编码密钥。
性能
数据结构先看语义再看复杂度;顺序与重复无关的重复成员检查用 set。当工作负载与周边架构能从 I/O 重叠中获益时使用 async/并发,不要仅因工作是 I/O 密集就把同步代码改成异步;绝不用可避免的同步 I/O 阻塞已有异步事件循环。只缓存已被证明重复且昂贵的计算,且需理解失效、内存与并发语义。在测量出实质瓶颈前优先清晰惯用代码;优化已测量的路径,当性能是契约时保留基准。
标识符命名
公开函数名、方法名、类名中展开缩写:gcd() 不直观,greatest_common_divisor() 自解释(来源:TheAlgorithms/Python CONTRIBUTING.md,访问于 2026-04-27)。领域内标准缩写可保留,按 PEP 8 在 snake_case 中用小写:url、api、sql、http、json、xml,例如 parse_url()、fetch_api_response()、run_sql_query()。生命周期不足 5 行的局部变量可用短名;引用超出定义后 5 行则展开缩写。不要“货物崇拜式隐私”:前导下划线是“有意非公开”的架构声明,不要仅因辅助函数、局部函数、模块常量、导入别名或实现细节“看起来私有”就加下划线。默认公开命名;仅当存在既定 API 边界、框架惯例、名称改写要求或具体冲突时才引入下划线。已有下划线应作为发现项,先弄清它防的是什么;若没有冲突,前缀只是习惯,应去掉。点号导入需要别名(import a.b 只绑定 a),优先 import a.b as ab 而非 import a.b as _ab。真实冲突应修复冲突本身而非改名:常见两种形态是包装器遮蔽其委托的函数、局部名遮蔽第三方名;冲突是缺陷,别名是症状。
脚本依赖与 UI/CLI
面向人的新 CLI 且可接受第三方依赖时,默认 Typer + Rich;随 Agent Skill 或插件分发的 CLI 优先稳定紧凑的 JSON 契约,不要为命令输出引入 Rich;既有项目保留其自洽的 CLI 框架与依赖策略。添加任何依赖前,需确认它能实质降低复杂度或强化所需契约,足以抵偿安装、兼容、供应链与维护成本;标准库已能清晰解决时用标准库。Rich 控制台输出始终使用 Rich emoji 记号(如 :white_check_mark:)而非字面 Unicode emoji,以保证跨平台兼容、渲染一致与 Markdown 安全对齐。Rich 表格与面板宽度模式使用 Measurement.get(console, console.options, renderable)。
测试与文档
测试优先(TDD):先针对已定义接口写失败测试,再实现逻辑。新项目优先 pytest,保留既有自洽测试框架;按测试接缝选择 fakes、依赖注入、monkeypatch 或 pytest-mock,不要仅为替换可用的 unittest.mock 而引入 pytest-mock。覆盖率覆盖变更行为、公开契约、边界、回归与有意义的失败路径;尊重既有覆盖率门槛,无门槛时不臆造百分比目标;检查未覆盖的变更分支风险;关键逻辑可用变异测试增强信心。测试质量遵循 AAA(Arrange-Act-Assert);测试名描述行为而非实现(如 test_process_payment_when_insufficient_funds_returns_declined);测试相互隔离独立。测试失败应视为潜在缺陷发现,采用“测试错 vs 实现错”双假设,绝不自动改测试去迎合实现。新公开 API 在签名与名称不足以表达契约,或需要说明行为、错误、单位、副作用、不变量时,优先简洁的 Google 风格 docstring;遵循既有文档风格。变更契约有消费者时同步更新文档、示例、架构记录、变更日志/发布说明与生成产物。
工具链默认
新项目默认:uv 管理依赖、ruff 做 lint 与格式化、ty 做类型检查、pytest 做测试、hatchling 作为构建后端。既有项目工具链在自洽且受支持时具有权威性;使用 hooks/CI 实际强制执行的命令与配置,不要添加并行工具。
评审与修订规范
规范是活的文档。发现新最佳实践、缺失的生态工具,或此处规则与官方 Python 文档矛盾时,应更新本文档。流程:识别缺口(触发条件是智能体反复遇到的失败模式、进入生态的新工具或明确的标准更新请求);对照一手来源验证(Python PEP 或官方库文档 docs.python.org、docs.pytest.org、docs.astral.sh;对真实代码的实测扫描也算一手来源,需记录可复现的命令与提交);与第 1 节比较(概念缺失或现有规则即反模式时存在缺口);写入对应子节,保持简洁、祈使、不含计数或仓库特定路径;验证新规则与文档其余部分不矛盾。