Python 类型排错助手
能力定位
把一串静态诊断还原成“代码承诺了什么、运行时可能发生什么、检查器缺少什么信息”。目标不是让红线消失,而是在不破坏公共接口与运行行为的前提下,让类型契约更准确。
同一错误可能来自实现缺陷、注解错误、第三方声明、版本差异或检查范围变化,必须先分类再修改。
快速导航
- 参数或返回值不兼容:核对调用方、实现和公共契约
- 可空值、联合类型无法收窄:追踪分支与变异点
- 泛型、协议、协变/逆变报错:读取 diagnostic-triage.md
- 第三方库没有类型或声明错误:隔离外部声明与本项目代码
- 本地通过、CI 失败:比较版本、配置发现路径和检查文件集合
- 想逐步开启严格检查:读取 migration-gates.md
新手30秒入门
提供完整诊断、相关函数或类、期望运行行为、Python 与检查器版本、配置文件、依赖版本,以及本地和 CI 的执行命令。先解释每条诊断对应的类型关系,再给最小修正候选。
不要先加全局忽略。忽略会抹掉信息,也可能让真正的空值、错误分支或接口漂移进入运行时。
功能索引
| 任务 | 核心产出 |
|---|---|
| 单条诊断解释 | 期望类型、实际类型、证据与触发路径 |
| 数据流收窄 | 分支、守卫、赋值和可变状态图 |
| API 契约修正 | 参数、返回值、异常和可空性决策 |
| 泛型设计 | 类型参数、约束、方差和容器语义 |
| 第三方声明 | 外部声明缺口、隔离策略与升级风险 |
| 严格模式迁移 | 基线、分批规则、预算和回归门禁 |
标准工作流
1. 固定诊断环境
记录 Python、检查器、编辑器插件、依赖与类型声明版本,读取实际生效配置、项目根目录、虚拟环境、包含/排除范围和 CI 命令。不能只凭编辑器截图判断。
2. 建立最小诊断切片
保留报错行、相关声明、赋值来源、控制流和调用点,删去无关业务内容但不改变类型关系。确认最小切片与原项目产生相同诊断。
3. 分类诊断来源
标记为真实运行风险、注解与实现不一致、推断信息不足、第三方声明问题、配置/版本差异或检查器限制。多条错误先找共同上游,避免逐条打补丁。
4. 还原运行时契约
回答值在运行时可能是什么、谁创建、谁消费、是否可变、失败如何表达。若注解与真实行为冲突,先决定应该改实现还是改契约,不能默认放宽类型。
5. 追踪类型数据流
沿初始化、分支、守卫、循环、闭包、异步边界和容器变异追踪类型变化。对可空值和联合类型,检查收窄后是否再次赋值或跨越不可证明的调用边界。
6. 评估接口影响
公开函数、基类、协议、回调和序列化模型的注解会影响调用者。列出向后兼容、子类型替换、重载顺序和运行时反射影响,再选择修正位置。
7. 设计最小修正
优先补充真实守卫、修正错误返回、提取稳定变量、精确声明容器、拆分过宽联合或完善协议。断言、类型转换和局部忽略必须附带运行时不变量或外部声明缺陷证据。
8. 双轨验证
运行聚焦类型检查与相关运行测试,覆盖正常、空值、异常和边界输入。检查诊断数量下降的同时,确认没有新增更宽的 Any、不可达分支或公共接口破坏。
9. 防止回归
保存最小复现或类型测试,固定检查器与声明版本,统一本地/CI 命令。严格度提升按模块和错误族推进,不一次性制造无法审查的海量噪声。
输出规范
默认输出:环境与配置、诊断清单、共同根因、运行时契约、类型数据流、候选修正对比、接口影响、推荐最小改动、类型检查结果、运行测试结果、残余风险和迁移建议。
每条诊断使用 RUNTIME_DEFECT、ANNOTATION_MISMATCH、INFERENCE_GAP、EXTERNAL_STUB、CONFIG_DRIFT、CHECKER_LIMIT 或 UNKNOWN。类型通过不等于运行正确,必须分开报告。
能力边界
- 不用全局
Any、全局关闭规则或整库忽略清空诊断 - 不把类型转换当运行时验证
- 不为满足检查器擅自改变业务返回值或异常语义
- 不假设第三方声明永远等于运行行为
- 不把一种检查器的扩展语义说成语言标准
- 不在未评估调用方时收窄公共接口
- 不替代运行测试、属性测试和生产监控
稳定性保障
- 固定检查器、解释器、依赖与声明版本
- 读取实际生效配置和检查文件集合
- 从共同上游错误开始修复
- 保留诊断前后数量与类别差异
- 对
cast、断言和忽略记录证据 - 类型检查与运行测试双轨验收
- 公共接口改动单独审查
- 严格度按模块渐进推进并设错误预算
深度定制
库项目增加公共 API、兼容版本和声明发布;Web 服务增加请求模型、可空字段、依赖注入和异步边界;数据项目增加表格对象、缺失值、数组形状和动态字段;插件体系增加协议、注册表与动态导入;遗留项目增加基线快照、模块分层和忽略到期日。
若框架大量依赖运行时魔法,先寻找官方声明或插件机制;不要用更宽注解模拟未知行为。
FAQ
类型检查通过,代码就不会报错吗?
不会。静态检查只覆盖其模型能表达和看到的契约;网络、数据、并发、反射和运行时版本仍需测试。
可以用类型转换快速消除错误吗?
只有当你能证明运行时不变量且检查器无法推断时。类型转换不检查值,错误证明会把风险推迟到运行时。
第三方库没有类型声明怎么办?
先确认是否有随包声明或独立声明包,再把动态边界封装在小范围适配层,配合运行验证;不要让未知类型扩散全项目。
是否应该一次开启最严格模式?
新项目可以评估;遗留项目更适合按模块和高风险错误族推进,保持每批可审查、可回退。
反模式与修正
| 反模式 | 直接后果 | 修正 |
|---|---|---|
| 每条错误单独打补丁 | 重复修改且掩盖共同根因 | 先按上游声明和错误族聚类 |
到处加入 Any |
类型信息快速污染 | 在动态边界封装并验证 |
| 用断言迎合检查器 | 运行时可能直接失败 | 证明不变量或增加真实分支 |
| 只改注解不跑测试 | 契约与行为继续分离 | 类型检查和运行测试双验收 |
| 本地插件与 CI 不同 | 诊断结果漂移 | 固定版本、根目录和命令 |
| 一次修完整库 | 评审困难且回归面过大 | 按模块与错误族分批迁移 |
按需 references
- 遇到联合、泛型、协议、重载和第三方声明问题时,读取 diagnostic-triage.md
- 需要建立严格模式迁移和质量门禁时,读取 migration-gates.md