# ChatGPT Plus 辅助分析 Python 异常堆栈:从日志脱敏到回归测试

ChatGPT Plus 辅助分析 Python 异常堆栈:从日志脱敏到回归测试

在 Python 项目中遇到异常时,直接把整段日志复制给 ChatGPT Plus,再输入"帮我修复",通常不是最可靠的做法。

完整日志可能包含无关信息、真实路径、服务器地址和用户数据;缺少运行环境、输入样本和业务约束时,模型也只能根据常见情况猜测。一个更稳妥的调试流程应该包括:

  1. 从堆栈底部确认异常类型和触发位置;
  2. 对日志和配置进行脱敏;
  3. 提取最小可复现代码;
  4. 第一轮只分析原因,不修改代码;
  5. 第二轮限定最小修复范围;
  6. 使用本地测试验证,而不是直接相信生成结果。

本文用一个 Decimalfloat 混用的示例,演示如何让 ChatGPT Plus 辅助分析 Python 报错,同时保留人工审查、版本控制和回归测试(环球巴士整理)。

一、示例问题:Decimal 与 float 混用

假设项目中有一个用于计算含税价格的函数:

python 复制代码
from decimal import Decimal


def price_with_tax(price: Decimal, tax_rate: float) -> Decimal:
    return price * (Decimal("1") + tax_rate)


print(price_with_tax(Decimal("100.00"), 0.06))

运行代码:

bash 复制代码
python pricing.py

会得到类似下面的异常:

text 复制代码
Traceback (most recent call last):
  File "pricing.py", line 8, in <module>
    print(price_with_tax(Decimal("100.00"), 0.06))
  File "pricing.py", line 5, in price_with_tax
    return price * (Decimal("1") + tax_rate)
                    ~~~~~~~~~~~~~^~~~~~~~~~
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'

问题并不复杂:Decimal("1")Decimal,而 tax_ratefloat,Python 不允许直接把这两种数值类型相加。

但真实项目中的堆栈往往更长,还可能经过 Web 框架、数据库驱动和多个业务函数。如果只把日志交给模型,而不说明哪些代码属于自己、哪些来自依赖,回答很容易偏离问题。

二、先学会从异常堆栈底部向上读

Python 异常堆栈通常可以按下面的顺序阅读。

1. 最后一行:异常类型和直接原因

text 复制代码
TypeError: unsupported operand type(s) for +: 'decimal.Decimal' and 'float'

这一行给出了三个关键信息:

  • 异常类型是 TypeError
  • 失败运算是加法;
  • 两边的类型分别为 Decimalfloat

2. 倒数第二个业务栈帧:真正触发错误的位置

text 复制代码
File "pricing.py", line 5, in price_with_tax

如果堆栈中同时存在第三方库和项目代码,优先检查最靠近异常底部的业务代码栈帧,而不是立即修改依赖包。

3. 更上层栈帧:输入从哪里进入

text 复制代码
File "pricing.py", line 8, in <module>

这一层说明函数接收到的 tax_rate 是浮点数 0.06。如果真实项目中的值来自 JSON、数据库或环境变量,还要继续检查类型转换发生在哪里。

三、把日志交给 ChatGPT 前先脱敏

开发日志中常见的敏感信息包括:

  • Windows 或 Linux 用户目录;
  • 服务器 IP、端口和内部域名;
  • 数据库连接字符串;
  • Cookie、访问令牌和 API Key;
  • 邮箱、手机号、订单号和用户 ID;
  • 未公开的仓库地址和项目名称。

例如下面的日志不适合直接复制:

text 复制代码
POST internal-api.example.local/orders/849312
Authorization: Bearer TOKEN_VALUE
Database: postgresql://admin:PASSWORD_VALUE@10.0.0.8/prod
User email: user@example.com

可以改成:

text 复制代码
POST INTERNAL_HOST/orders/ORDER_ID
Authorization: Bearer YOUR_TOKEN
Database: postgresql://USER:PASSWORD@HOST/DATABASE
User email: USER_EMAIL

脱敏不能只做字符串替换,还要检查上下文。某些订单号、文件名或目录结构即使没有姓名,也可能暴露业务信息。

四、第一轮提示词:只分析,不生成修复代码

把最小代码和异常信息整理好后,可以先让 ChatGPT Plus 解释问题:

text 复制代码
请分析下面的 Python 异常,只说明能够从代码和堆栈直接证明的原因,暂时不要修改代码。

运行环境:
- Python 3.12
- 不使用第三方数值库

业务约束:
- price 使用 Decimal;
- tax_rate 表示 0 到 1 之间的税率;
- 金额计算不能退回 float;
- 当前公共函数名称和参数数量不能改变。

请按下面格式输出:
1. 直接原因;
2. 数据类型如何进入函数;
3. 可能受影响的边界情况;
4. 修复前需要确认的问题。

代码:
[粘贴最小复现代码]

异常:
[粘贴脱敏后的堆栈]

这一步故意不要求模型立即给出代码,原因有两个:

  1. 先确认模型是否正确理解异常;
  2. 避免它在没有业务约束时进行大范围重构。

如果第一轮分析已经出现错误,例如建议把全部金额改成 float,就应该先纠正前提,而不是继续让它生成补丁。

五、第二轮提示词:限定最小修复范围

确认原因后,再提出具体修改要求:

text 复制代码
请给出最小修复方案,必须满足:

- price 和返回值继续使用 Decimal;
- tax_rate 允许传入 Decimal、字符串或整数;
- 不接受 float,避免二进制浮点误差被带入金额计算;
- tax_rate 必须位于 0 到 1 之间,包含边界;
- 非法类型抛出 TypeError;
- 非法范围抛出 ValueError;
- 不引入第三方依赖;
- 输出修改后的函数和 pytest 测试;
- 不修改其他文件。

这里主动规定"不接受 float",是为了让接口边界更明确。如果业务系统当前已经大量传入浮点数,也可以选择兼容,但必须先决定如何转换以及是否接受精度变化。

六、一个可审查的最小修复

下面是一种实现方式:

python 复制代码
from decimal import Decimal, InvalidOperation
from typing import Union


TaxRateInput = Union[Decimal, str, int]


def normalize_tax_rate(value: TaxRateInput) -> Decimal:
    if isinstance(value, float):
        raise TypeError("tax_rate must not be float")

    if not isinstance(value, (Decimal, str, int)):
        raise TypeError("tax_rate must be Decimal, str, or int")

    try:
        rate = value if isinstance(value, Decimal) else Decimal(str(value))
    except InvalidOperation as exc:
        raise ValueError("tax_rate is not a valid decimal value") from exc

    if not rate.is_finite():
        raise ValueError("tax_rate must be finite")

    if not Decimal("0") <= rate <= Decimal("1"):
        raise ValueError("tax_rate must be between 0 and 1")

    return rate


def price_with_tax(price: Decimal, tax_rate: TaxRateInput) -> Decimal:
    if not isinstance(price, Decimal):
        raise TypeError("price must be Decimal")

    rate = normalize_tax_rate(tax_rate)
    return price * (Decimal("1") + rate)

这个版本做了几件事:

  • 明确拒绝 float
  • 将字符串和整数统一转换为 Decimal
  • 区分类型错误与数值范围错误;
  • 保留原函数名称和参数数量;
  • 没有引入第三方依赖。

是否需要单独的 normalize_tax_rate 函数,取决于项目规模。如果转换逻辑只使用一次,可以放回原函数;如果多个模块都处理税率,独立函数更便于测试和复用。

七、补充 pytest 回归测试

为修复代码添加测试:

python 复制代码
from decimal import Decimal

import pytest

from pricing import price_with_tax


@pytest.mark.parametrize(
    ("price", "tax_rate", "expected"),
    [
        (Decimal("100.00"), Decimal("0"), Decimal("100.00")),
        (Decimal("100.00"), Decimal("0.06"), Decimal("106.0000")),
        (Decimal("100.00"), "0.06", Decimal("106.0000")),
        (Decimal("100.00"), 1, Decimal("200.00")),
        (Decimal("0"), "0.25", Decimal("0.00")),
    ],
)
def test_price_with_tax_valid_input(price, tax_rate, expected):
    assert price_with_tax(price, tax_rate) == expected


@pytest.mark.parametrize("tax_rate", [0.06, object()])
def test_price_with_tax_rejects_invalid_type(tax_rate):
    with pytest.raises(TypeError):
        price_with_tax(Decimal("100.00"), tax_rate)


@pytest.mark.parametrize(
    "tax_rate",
    [Decimal("-0.01"), Decimal("1.01"), Decimal("NaN"), "invalid"],
)
def test_price_with_tax_rejects_invalid_value(tax_rate):
    with pytest.raises(ValueError):
        price_with_tax(Decimal("100.00"), tax_rate)


def test_price_with_tax_rejects_non_decimal_price():
    with pytest.raises(TypeError):
        price_with_tax(100.0, Decimal("0.06"))

运行测试:

bash 复制代码
python -m pytest -q

如果项目还使用 Ruff 或 Mypy,可以继续执行:

bash 复制代码
ruff check .
mypy .

工具名称和配置要以项目实际情况为准,不需要为了文章示例临时引入一套新的检查工具。

八、测试代码也要人工审查

AI 生成测试不代表测试一定有效。至少要检查下面几个问题:

1. 测试是否覆盖了业务边界

本例需要覆盖:

  • 税率等于 0
  • 税率等于 1
  • 税率小于 0
  • 税率大于 1
  • 浮点数输入;
  • 无法转换的字符串;
  • price 不是 Decimal

2. 测试是否只验证了当前实现

如果测试完全照着实现细节编写,可能只是重复代码,而不是验证业务规则。测试应描述外部可观察行为,例如返回值和异常类型。

3. 是否为了通过测试而降低要求

当测试失败时,不应该直接删除断言、扩大允许范围或捕获所有异常。先确认失败来自需求、实现、测试数据还是运行环境。

九、使用 git 检查修改范围

在接受任何 AI 生成的修改前,先查看工作区:

bash 复制代码
git status --short
git diff --check
git diff

重点检查:

  • 是否修改了约定范围以外的文件;
  • 是否意外改变公共函数签名;
  • 是否加入没有说明的新依赖;
  • 是否把真实日志、令牌或本地路径写进测试;
  • 是否删除了原有测试;
  • 是否出现大面积格式化导致 Diff 难以审查。

对于规模较大的修改,可以要求 ChatGPT 先输出文件清单和实施计划,确认后再逐个文件处理。

十、适合复制的异常分析模板

下面这个模板可以用于大多数 Python 报错:

text 复制代码
请分析这个 Python 异常。

运行环境:
- Python 版本:
- 操作系统:
- 主要依赖及版本:

预期行为:

实际行为:

最小复现步骤:
1.
2.
3.

业务约束:
- 不能修改:
- 必须保留:
- 允许修改:

请先只输出:
1. 能够从代码直接证明的原因;
2. 触发条件;
3. 仍缺少的信息;
4. 最小修复计划。

在我确认计划前,不要生成完整重构代码。

模板不需要每次全部填写。简单问题可以缩短,但运行环境、预期行为、实际行为和最小复现通常不能省略。

十一、常见问题

1. 可以把整个项目压缩后直接上传吗?

不建议把未筛选的完整项目直接作为第一步。应先排除 .env、密钥、证书、数据库备份、用户数据、构建产物和无关依赖,再从最小模块开始分析。

2. 堆栈太长,应该截取哪一部分?

至少保留异常类型、完整错误消息、最靠近异常位置的业务栈帧,以及能够说明输入来源的上层栈帧。不要只截最后一句,也不必保留几千行重复日志。

3. ChatGPT Plus 给出的代码可以直接用于生产环境吗?

不可以直接使用。生成代码应经过人工审查、本地测试、集成测试和必要的安全检查,高风险变更还需要审批和回滚方案。

4. 为什么同一个报错每次得到的建议不同?

模型输出存在一定变化,上下文和提示词也会影响结果。使用固定的最小复现、明确约束和可执行测试,比依赖某一次回答更可靠。

十二、总结

使用 ChatGPT Plus 分析 Python 异常堆栈时,重点不是让模型尽快输出一段修复代码,而是建立一个可复现、可审查、可验证的流程:

  1. 从堆栈底部确认异常和触发位置;
  2. 对日志、路径和配置进行脱敏;
  3. 提取最小复现代码;
  4. 第一轮只分析原因;
  5. 第二轮限制修改范围;
  6. 添加边界测试和异常测试;
  7. 通过 git diff 与本地测试验证结果;
  8. 最终由开发者决定是否采用修改。

ChatGPT Plus 可以帮助缩短信息整理和方案探索的时间,但代码是否正确,仍然要由运行结果、测试和人工评审来证明(本文由环球巴士整理,一站式账号服务)。

资料说明

  • Python 官方文档:decimal 模块
  • Python 官方文档:异常与回溯信息
  • pytest 官方文档:参数化测试与异常断言

本文示例为原创最小复现,代码仅用于演示异常分析方法。实际项目应根据业务规则、依赖版本和团队规范调整。

相关推荐
半亩码田4 小时前
AI周报 | DeepSeek-V4-Flash 正式版(7-31)、Wan2.6 全链路、GPT-5.6 降价 80%(上周 07.27-08.02)
人工智能·gpt
梦想的颜色7 小时前
2026 硬核横评:DeepSeek‑V4‑Flash VS OpenAI Codex (GPT‑5.6‑Codex) 代码模型全方位对比
gpt·codex·deepseek·ai 代码大模型·大模型 api 选型
灵极海11 小时前
Claude Code 理论介绍:给新手看的 AI 编程智能体入门
人工智能·chatgpt
武子康14 小时前
GPT-5.6 Sol 的 ARC-AGI-3 分数为何翻近三倍:Agent 评测必须记录整套运行合同
人工智能·chatgpt·agent
Canace15 小时前
GPT-5.6 到底怎么选?一文搞懂 Sol、Terra、Luna 和 Ultra
前端·人工智能·chatgpt
一次旅行16 小时前
OpenAI 新版提示词指南
人工智能·chatgpt·github
Lei活在当下1 天前
如何在Windows环境选择适合自己的 AI Agent
chatgpt·agent·ai编程
天地会珠海分舵1 天前
DeepSeek v4 flash vs GPT 5.6 Luna 测评报告!
gpt·deepseek·测评报告
fb_123451 天前
Linux磁盘分区从入门到实操:MBR_GPT全解析+分区工具实战指南
java·linux·gpt