
做技术评审做了快十年我越来越意识到一件事代码审查不能只靠人眼。于是我把目光放到了自动化审查工具上Sourcery AI 就是在那个时候进入我的工具箱的。简单说它专攻 Python 代码的审查与重构建议能在代码提交前帮你完整扫一遍也能在 GitHub 的 Pull Request 里自动留下点评相当于给团队配了一个永远不喊累的“第一轮评审”。它解决的问题非常具体代码里的低级问题太多评审人的时间不够真正重要的逻辑讨论总被琐碎意见淹没。无论你是刚接触 Python 的新人还是带多个开发者的技术负责人这篇文章都值得照着用起来。我会从安装注册讲起覆盖本地扫描、GitHub App 集成、配置文件定制、常用规则复盘以及我在真实项目里踩过的几个坑。整个过程中你会看到大量真实代码片段可以直接复制到自己的仓库里试验。1. 认识 Sourcery AI它和传统 Linter 有什么不同1.1 代码审查的真正痛点在哪先聊一个所有团队都绕不开的问题Code Review 为什么总是做不好我见过太多这样的情况——PR 一打开20 条评论里有 15 条是“这里少了个空格”“这个变量命名不符合规范”“这段代码可以写成列表推导式”。不是说这些意见不该提而是当低级问题占据了评审人的精力真正需要深度思考的架构设计、边界条件和性能风险反而没人好好看。更麻烦的是人工评审的一致性。同一个问题今天 A 评审会提明天 B 评审可能就放过了新人写的代码被挑出 50 处毛病老手写的代码可能只有 5 处但不是因为更优秀而是因为大家习惯了。这种不确定性会让团队对 Code Review 慢慢失去敬畏感最后变成“走过场”。自动化工具能解决一半问题但传统的 Linter 解决得很有限。Flake8 和 Pylint 擅长检查语法错误、PEP8 风格和明显的逻辑问题但它们很少告诉你“这段代码可以更简洁”“这两个 if 可以合并”“你这个累赘的分支完全可以去掉”。换句话说Linter 更像交通警察只管你有没有违章不管你开车的姿势是不是更省油。而 Sourcery 的角色更像一个驾校教练它专门盯着你哪些地方能优化还会把优化后的写法直接摆在你面前。这也是我当初把 Sourcery 引入团队的核心原因它能接住代码审查链条中最容易被消耗的那一层把“看得见的优化”自动处理掉。1.2 Sourcery 的本质规则引擎而不是大模型先讲清楚一个容易误会的点。Sourcery 名字里有 AI但它背后不是 ChatGPT 那种大语言模型。它是一个静态分析工具本质是一套被工程经验反复打磨过的规则引擎通过解析 Python 抽象语法树识别代码里的“坏味道”并预测出重构后的等价写法。为什么我说这是它的优点而不是缺点因为规则引擎意味着每条建议都可解释、可复现、可控制。它认为某个函数应该提前返回会明确告诉你依据是哪条规则修改后的代码长什么样。这种确定性让团队能放心把它接入 CI不会被一个概率模型偶尔抽风带偏方向。拿它和传统工具做个对比会更清楚。工具主要关注点输出形式典型特点Flake8语法错误、PEP8 风格报错与警告轻量、快、规则严格Pylint代码质量、复杂度评分与警告指标全面但误报也多Black代码格式化自动改写源码风格统一不关注逻辑Sourcery重构机会、代码简化建议或自动改写直接给出等价但更优的代码从这个表能看出Sourcery 的位置不是替代谁而是补上“重构建议”这一格。它检查的不是你的代码能不能跑而是你的代码能不能写得更像老手。所谓“让 AI 成为代码审查专家”准确理解应该是把专家积累的审查经验固化成一套随时可用的自动化规则。2. 本地快速上手五分钟跑通第一次扫描2.1 安装、登录与第一个命令如果你是 pip 用户安装很简单pip install sourcery装完先确认版本sourcery --version接下来是大多数人会忽略的一步登录。Sourcery 的本地命令行工具需要登录后才能使用完整规则库。运行sourcery login它会引导你打开一个授权链接完成账号绑定。这一步不需要担心免费体验的额度足够你试跑一个中型项目。要注意的是如果你在公司电脑上操作先确认公司对第三方代码分析工具的态度有部分团队不允许代码片段离开内网环境。登录完成后随便找一个 Python 项目跑一次完整审查sourcery review .这条命令会自动递归扫描当前目录下所有 Python 文件并在终端里输出每个文件的建议汇总。如果你只想看某一个文件直接把文件名传给它就行。我第一次跑这条命令时一个大约 2000 行的模块被列了 47 条建议。说实话当时有点震惊因为那个模块刚被公司里的老工程师“认真”review 过。仔细看内容才发现多数建议不是错误而是“可以更简洁”。这个体验让我立刻确定了它的价值定位用来兜底和提效而不是用来批判人。2.2 review 与 refactor只报告还是直接改Sourcery 本地命令最核心的两个动作分别是 review 和 refactor很多人一开始分不清。review是只读操作扫描代码并输出建议不会改动任何文件。适合想知道项目有多少“问题”时的快速体检也适合在 CI 里作为检查关卡。refactor则更激进它可以直接把代码改成最优形态。但我不建议你在没看过 diff 的情况下直接改。更稳妥的顺序是先预览sourcery refactor --check .--check会打印出所有将要发生的改动但不会落地。确认没问题后再执行真正的重写sourcery refactor --in-place target_file.py这里有一个我自己的习惯无论 Sourcery 的建议看起来多合理自动修改之后我一定会打开 git diff 看一眼。原因很简单规则引擎优化的是“可读性”和“简洁性”但不一定理解你业务代码里藏着的历史包袱。比如某个变量看起来冗余但它是为了调试时打日志才故意保留的这种上下文机器不知道。如果你不想到处敲子命令直接运行sourcery它会进入交互式模式一条一条展示建议并让你选择接受、拒绝还是忽略。这个模式在本地整理代码时很好用像有人坐在旁边陪你重构。2.3 给 Sourcery 加个触发器编辑器插件与提交钩子命令行工具适合定时扫描但最好的体验是把审查动作前置到“写代码的那一刻”。Sourcery 官方提供了 VS Code 和 JetBrains 系列插件装上之后你每写几行代码编辑器右侧就会实时出现重构建议。这种即时反馈对新人尤其友好它能在坏习惯固化之前完成纠偏。除了编辑器团队内部更推荐的触发点是 Git 提交钩子。你可以在 pre-commit 阶段运行 Sourcery让不满足基本审查门槛的代码根本进不了版本库。思路大致是sourcery review --check $如果扫描出建议就让提交失败开发者处理完再重新提交。这里要强调一个度提交钩子的规则要克制只保留团队一致认可的高置信度规则否则频繁拦截会让人想砸键盘。我见过一个团队把默认规则全开了结果平均每次提交要处理 8 条意见两天后钩子就被悄悄绕过了。3. 把 Sourcery 嵌进团队工作流GitHub 代码审查实战3.1 在 GitHub 上安装 Sourcery App本地扫描只能服务个人要让“AI 审查专家”成为团队流程的一部分最直接的方式是接入 GitHub。在 GitHub Marketplace 里搜索 Sourcery 并安装到你的组织或个人账号然后选择生效仓库。安装完成后团队里所有人的 Pull Request 都会被自动审查。那它的实际行为是什么样的每当有人新开 PRSourcery 会扫描这次改动涉及的 Python 文件然后把意见以一条汇总评论的形式追加到 PR 里。注意是汇总评论不是每条意见刷一条消息。这一点很关键否则高频率仓库的 PR 页面会被塞满垃圾评论嘈杂到无法正常讨论。用 GitHub App 和本地扫描相比最大的好处是统一。规则配置跟着仓库走每个人在同一套标准下接受审查不存在“我电脑上没跑出问题”的借口。而且历史 PR 会被留档团队可以回溯某个规则上线前后的代码改善情况。不过安装 App 时要注意权限范围。Sourcery 需要读取仓库代码才能完成分析如果组织里有很多敏感仓库最好只把它安装到需要执行的几个项目上避免不必要的代码暴露面。3.2 .sourcery.yaml 配置文件精读要让 Sourcery 稳定服务团队不能让它取默认值跑到底必须用配置文件把规则和忽略范围固定下来。社区和实践里最常用的配置文件是放在仓库根目录下的.sourcery.yaml。下面这个简化版配置是一个比较通用的起点version: 1 ignore: - tests/**/* - migrations/**/* - **/*.generated.py rule_settings: disabled: - use-named-expression - use-fstring-only enabled: - simplify-constant-if - simplify-boolean-expression - merge-nested-if先看ignore字段。它定义哪些路径不需要审查。测试文件、数据库迁移脚本、自动生成代码通常都应该放进忽略列表。这些文件要么不追求极致的可读性要么是工具产物改了反而影响后续生成。再看rule_settings。disabled下面列的是你明确不想启用的规则enabled下面列的是你想强制开启的规则。哪些要禁用、哪些要启用需要根据团队偏好决定不能拍脑袋。配置文件一旦提交到仓库所有协作者本地扫描和 GitHub App 都会读取同一份配置。这也意味着配置变更本身就是一次代码评审比口头约定可靠得多。值得提醒的是不同版本的 Sourcery 所支持的规则名称会有差异。新增一个规则之前先在本地运行命令确认规则确实存在再写进配置文件避免线上 App 读到不认识的规则名时直接报错。3.3 如何避免它干扰正常的评审节奏工具接入得越深越容易产生一个问题习惯性忽略。当 Sourcery 每次都给出十条评论开发者会逐渐对反馈麻木连真正重要的建议也一起无视这就失去了工具的意义。我的建议是分三步控制噪音。第一步在项目起步阶段只开最保守、置信度最高的规则比如“移除冗余 pass”“使用列表推导式”这类几乎没有争议的建议。第二步运行一段时间后每周复盘一次评论内容把那些“改了能行、但业务可读性反而变差”的规则一一加入 disabled。第三步对于历史包袱较重的目录用 ignore 字段暂时排除等团队重构完毕再逐步纳入审查。另外对 GitHub 评论的响应姿态也要立好规矩Sourcery 给的不是判决而是参考。开发者觉得某条建议不适合当前场景可以合理关闭评论或使用注释跳过不需要觉得是在“对抗 AI”。工具是帮助团队达成共识的不是制造新对立的。4. 最常用的十类审查建议代码示例复盘4.1 简化篇列表推导、条件合并、恒真假分支Sourcery 最拿手的一类建议是“简化”。先看列表推导式产生的最典型场景。# 改前 result [] for item in items: if item.is_valid(): result.append(item.id) # 改后 result [item.id for item in items if item.is_valid()]改前的写法没有任何错误但它用四行完成了一行能表达清楚的工作。Sourcery 会建议你使用列表推导不是因为列表推导更酷而是因为它在大多数情况下更易读也能减少无谓的循环控制逻辑。另一种高频建议是合并嵌套 if。# 改前 if user: if user.is_active: login(user) # 改后 if user and user.is_active: login(user)类似的还有恒真假条件。# 改前 if len(items) 0: return items[0] # 改后 if items: return items[0]这类建议的核心逻辑是Python 的布尔判断天然支持对象的真值语义空列表就是 False非空就是 True。人为写len(items) 0反而让代码显得冗余。4.2 表达篇f-string、链式比较与海象运算符现代 Python 引入了很多更清晰的表达方式Sourcery 会很积极地推动你的代码跟上版本特性。比较典型的是字符串格式化# 改前 message Hello, name ! You are str(age) years old. # 改后 message fHello, {name}! You are {age} years old.f-string 的价值不只是少打几个加号更重要的是不用再纠结 str() 和变量类型转换整体阅读流畅度也更好。如果你的项目 Python 版本支持 f-string这个建议基本可以无脑接受。链式比较也是它的常客# 改前 if value 10 and value 20: pass # 改后 if 10 value 20: pass至于海象运算符:Sourcery 会把这种模式assigned pattern.search(data) if assigned: handle(assigned)改写成if assigned : pattern.search(data): handle(assigned)我个人对这个规则比较纠结。它确实让代码少了一行但对一部分还不熟悉海象运算符的开发者来说可读性是下降的。所以我在团队配置文件里把这个规则默认禁掉了想用的人可以在具体分支里临时用而不是让新人被这种写法惊吓到。4.3 清理篇冗余 else、无谓 pass 和多余赋值代码经过多轮修改后最容易留下“已经没必要存在”的结构。Sourcery 在清理这类垃圾方面特别勤快。最常见的是不必要的 else。# 改前 def check_status(status): if status ok: return True else: return False # 改后 def check_status(status): return status ok很多人在写简单判断时习惯性带上 else但 return 语句执行后就退出函数了else 在这里没有任何价值。删掉它可以让代码的意图更直接。冗余 pass 也经常出现# 改前 def placeholder(): pass # 改后 def placeholder(): placeholder function一个只有 pass 的函数通常意味着开发者准备以后实现但直接留空很容易让人觉得是忘了写。Sourcery 会建议你补一个 docstring既保留了占位语义又不触发空函数警告。还有一类是“先赋值再加料”的模式# 改前 config {debug: True} config.update(defaults) # 改后 config {**defaults, debug: True}这种改写会把一个连续的初始化动作合并到一个表达式里避免变量被多次重新赋值。4.4 我的规则取舍清单工具好不好用不看它能提多少建议看你敢启用多少建议。下面这份规则取舍清单来自我在团队里的实践不同项目可以直接抄作业。建议类型适用场景我的取舍策略列表推导式简单的遍历筛选默认启用数据量大且逻辑复杂时例外合并嵌套 if条件短且语义清晰默认启用禁止合并含长注释的条件f-string 转换字符串拼接场景默认启用链式比较区间判断默认启用海象运算符一次性使用变量的判断禁用除非团队普遍熟练删除冗余 elsereturn 后的分支默认启用合并字典初始化连续 update 操作按可读性评估不盲改恒真假条件简化明显冗余条件默认启用移除多余赋值简单转发场景确认变量无调试价值后启用这份清单的核心原则只有一句话低风险、高共识的规则全开高风险、低共识的规则全关。不要因为工具能提某个建议就强迫团队接受。5. 排坑实录误报、规则定制与性能问题5.1 误报不是 bug是配置不到位很多人在第一次用 Sourcery 时都会遇到一批看起来“不太对”的建议就断定工具不行。我的经验是大部分所谓误报根源在于没做规则定制。举个例子它经常建议把一种显式循环改成生成器表达式但在某些业务代码里循环体内还包含日志记录和统计埋点改成生成器会破坏这些副作用。这时代码改不改已经不是技术问题而是业务需要问题。正确做法不是抱怨工具蠢而是把这类规则从配置里禁用或在具体代码上方加跳过注释。Sourcery 支持类似于注释豁免的机制。你在函数或代码块上方写一行跳过指令工具就不会对该区域产生建议。# sourcery skip def legacy_function(): # 这里故意保留显式写法原因便于调试时插入日志 ...这种局部豁免非常实用它保留了团队的规则一致性又给特殊情况留了口子。我强烈建议团队把这些豁免注释当成第二种代码注释来维护每次有人新增跳过注释都应该想一想是规则真的不合适还是我们只是在给旧代码找借口5.2 大项目扫描太慢怎么办Sourcery 需要解析完整的 Python 抽象语法树项目一大本地全量扫描的时间会明显上升。我第一次在大概 20 万行代码的仓库里跑sourcery review .足足等了好几分钟体验相当糟糕。后来我改用增量扫描策略只审查本次提交涉及的文件。在 CI 里先通过git diff拿到变更文件列表再传给 Sourcery 处理。这个思路不复杂但能节省大量时间。具体流程大致是在 CI 脚本里获取本次 PR 变更的 Python 文件列表对这些文件逐个运行sourcery review只有建议输出时才让 CI 失败本地提交钩子也走同一套思路只检查 staged 文件而不是全仓库扫描。这样既不拖慢开发速度又能保证最常见的坏味道被拦在门外。5.3 和 Flake8、Black、Mypy 组成流水线Sourcery 进入工具箱之后很多团队会问一个问题那它是不是可以替代 Flake8、Black 和 Mypy我的答案是不行。这四个工具压根是在处理不同维度的问题。Flake8 管的是语法和基础风格Black 管的是格式化一致性Mypy 管的是类型安全Sourcery 管的是代码结构与可维护性。把它们放在同一条流水线里并行才是正确用法。以我目前团队的流水线为例拉代码后的检查顺序是固定的Black 先格式化Flake8 检查基础问题Mypy 做类型校验最后 Sourcery 跑重构建议。人工评审只看结果里最关键的逻辑与架构问题前三层能过滤掉将近八成的小噪音。这个顺序之所以有意义是因为如果代码还没有格式化Sourcery 看到的代码结构可能是混乱的给出的建议也会被格式问题干扰。先让格式收敛再让静态分析发挥作用准确度会更高。5.4 和 Sourcery 配合时最容易踩的三个坑第一个坑是无脑接受自动重构。我曾经让 Sourcery 直接重写一个核心模块结果它把几个带有副作用的列表推导式压缩成生成器表达式导致延迟计算的时机变化线上出现一个隐蔽的 bug。从那以后我再也不碰它默认的自动改写模式最多用refactor生成、人工确认。第二个坑是忽略规则版本差异。团队里不同成员的 Sourcery 版本不一致有人跑出来的建议有人跑不出来就会在 PR 里发生冲突。解决方式是在项目文档里锁好版本号或者直接统一用 GitHub App 作为唯一规则入口。第三个坑是把它当作唯一评审人。Sourcery 可以稳定发现“代码写得不好”的问题但发现不了“这个需求是否应该这么做”的问题。它弥补的是效率替代不了人工对业务逻辑的判断。一个真正健康的团队评审流程应该是工具打底人做判断。最后分享一个真实体会Sourcery 加入团队流程的第一个月我们统计过 PR 评论类型与格式、重构风格相关的评论占比下降了六成左右。这不是因为它比人聪明而是因为它从不厌倦、从不漏看、也从不动情绪。代码审查最耗时的那部分低垂果实都被它提前摘走了。我个人使用它的最终建议是把它当成签合同前的法务初审不要当成拍板定性的最终裁决。每个建议都看一遍能用的就用不能用的就用豁免机制说明原因。规则跟着团队一起进化比追求“全开”有价值得多。另外如果你所在团队的 Sourcery 规则库还在用很旧的版本建议挑一个集中时间升级并跑一次全仓库审查把新规则的意见当作一次免费的重构机会。代码审查工具最大的回报不是让你少干活而是让你把省下的时间花在真正需要人判断的问题上。