AI 编程助手可以快速生成函数、测试和接口代码,但“能运行”不等于“值得合并”。审查 AI 生成的 Python 代码时,自动化工具能帮我们发现格式、类型和常见缺陷,真正困难的部分仍然是验证业务语义、异常路径和边界条件。
先让工具完成机械检查
人工审查不应该从缩进、未使用变量或明显的类型错误开始。可以把格式化、静态检查、类型检查和测试放进同一条命令,让审查者把注意力放在行为上。
下面是一个可以直接改造的本地检查脚本。它假设项目使用 pytest、ruff 和 mypy;如果项目尚未采用类型检查,可以先删除 mypy 那一行。
#!/usr/bin/env bash
set -euo pipefail
python -m ruff format --check .
python -m ruff check .
python -m mypy src
python -m pytest -q
这些检查各自解决不同问题:
ruff format --check检查代码是否符合统一格式。ruff check发现一部分明显的错误、危险写法和无效导入。mypy帮助识别不一致的参数、返回值和可空值处理。pytest验证代码在已知场景下是否保持预期行为。
自动检查通过只能说明代码满足了部分机械约束,不能证明 AI 理解了需求。尤其要注意:测试本身可能覆盖不足,而 AI 生成的测试也可能只是重复实现同一个错误假设。
AI 代码最需要人工核对的地方
1. 需求是否被准确实现
审查时不要只问“这段代码是否合理”,而要逐条对照任务描述:输入允许哪些值?失败时应该抛出什么异常?是否允许重复调用?返回顺序是否有要求?时区、权限和事务边界由谁负责?
AI 很容易生成结构完整、命名清晰,却遗漏关键业务规则的代码。一个看似简单的过滤函数,可能把“没有结果”和“输入非法”都返回为空列表,导致上层无法区分两种情况。
2. 边界条件和异常路径
重点检查空集合、重复数据、极大或极小数值、缺失字段、超时、网络失败以及并发调用。正常路径通常最容易被示例覆盖,真正的缺陷往往隐藏在失败路径中。
例如,下面的函数可以这样实践:明确区分非法输入和没有匹配项,并通过测试固定这个契约。
from __future__ import annotations
def first_price_at_least(prices: list[float], minimum: float) -> float:
"""Return the first matching price, or raise a clear error."""
if minimum < 0:
raise ValueError("minimum must be non-negative")
for price in prices:
if price < 0:
raise ValueError("prices must not contain negative values")
if price >= minimum:
return price
raise LookupError("no price meets the minimum")
def test_first_price_at_least() -> None:
assert first_price_at_least([10.0, 25.0], 20.0) == 25.0
try:
first_price_at_least([10.0], 20.0)
except LookupError:
pass
else:
raise AssertionError("missing match must raise LookupError")
这段示例的重点不是实现复杂算法,而是把输入约束、返回语义和失败行为写清楚。审查 AI 代码时,同样应该要求这些行为在测试中可观察、可验证。
3. 状态、资源和副作用
AI 生成代码时,经常能写出“看起来正确”的函数,却没有处理文件、数据库连接、锁、临时目录或 HTTP 会话的生命周期。检查以下问题很有价值:
- 文件和网络响应是否使用上下文管理器关闭?
- 异常发生时,锁和临时资源是否释放?
- 重试是否可能重复提交订单、发送消息或扣款?
- 函数是否偷偷修改了传入的列表、字典或全局状态?
- 并发场景下,读取和更新是否需要原子操作?
例如,涉及文件时,优先确认代码是否使用 with open(...),而不是只看“文件内容能否读出来”。涉及外部服务时,还要检查超时、状态码、重试策略和日志中是否泄露凭据。
不要把“看起来专业”当成正确
AI 生成的代码往往有完整的 docstring、类型注解和测试名称,这些信号有助于阅读,却不能替代验证。审查者需要主动寻找反例:
- 类型注解是否与运行时真实数据一致?
Optional、空值和缺失键是否被区分?except Exception是否吞掉了本应暴露的错误?- 列表推导式或生成器是否改变了求值时机?
- 时区是否被错误地当作本地时间处理?
- 正则表达式、反序列化和 SQL 拼接是否带来注入风险?
- 日志是否记录了密码、令牌、个人信息或完整请求体?
一个实用的审查顺序是:先读需求和调用方,再读生成代码,接着运行自动检查,最后为关键假设补充反例测试。不要只从函数内部推断正确性,因为很多问题只有放回真实调用链后才会出现。
建议采用的审查清单
提交 AI 生成的 Python 代码前,可以逐项确认:
- 自动格式化、静态检查、类型检查和测试是否通过?
- 主要业务规则是否都能在代码或测试中找到对应位置?
- 正常输入、空输入、非法输入和极端输入是否分别验证?
- 异常是否被准确处理,而不是被静默吞掉?
- 文件、连接、锁和临时资源是否在所有路径上释放?
- 重试和幂等性是否符合业务后果?
- 外部输入是否经过验证,敏感数据是否得到保护?
- 测试是否验证行为,而不是机械重复实现代码逻辑?
- 变更是否足够小,方便回滚和定位问题?
AI 可以缩短编写代码的时间,却不能替开发者承担需求解释和风险判断。高效审查的核心,是把工具用于发现机械错误,把人工时间留给业务语义、失败路径、副作用和安全边界。