news 2026/10/19 19:41:56

开源代码审查工具 open-code-review 的原理与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
开源代码审查工具 open-code-review 的原理与实战

写代码这么多年,我一直觉得 code review 是最能体现团队技术氛围的一件事。代码写得好不好,review 别人代码时一针见血,说明你对自己写的东西有没有深入思考过。但现实很骨感,项目赶进度的时候,Review 往往是最先被牺牲的环节。我见过太多团队嘴上说"一定要 review",实际合并请求挂了两三天没人看,或者 Reviewer 只回一句"LGTM"就合进去了。这些场景背后都是同一个问题:人肉 review 的成本和效果不成正比。

于是我开始折腾自动代码审查,测试过好几款商业工具和开源项目,也在 CI 里折腾过各种静态扫描方案。今天想聊的是我目前在用的一个开源项目,叫open-code-review。它不是那种玄乎的 AI 魔法,也不是单纯的 linter,而是把静态分析、规则引擎和代码托管平台的交互串起来的一套自动化审查工具。说白了,它就是帮你把代码审查里那些重复性、机械性的部分交给机器,让人把精力聚焦在真正需要判断力的地方。

这篇文章会从项目设计的思路聊起,讲清楚它内部的规则机制、接入方式、在 GitLab/GitHub 上的实战效果,以及我踩过的一些坑。如果你正在纠结"要不要给团队上自动代码审查""用现成的商业版还是自己搭",这篇应该能给你一个比较完整的参考。

1. 项目整体设计与思路拆解

1.1 代码审查的痛点到底在哪

先说个我观察到的现象。很多团队并非不想做代码审查,而是Review的过程有天然的结构性问题。

第一个痛点是时效性。一个合并请求提出之后,早上的代码下午才有人看,下午的代码第二天才有人回应,等到所有讨论结束,分支可能已经落后主分支几十个提交了。这个时间差会导致两个后果:一是 Reviewer 需要在脑子里重新理解一次上下文,二是开发者会倾向于在 review 期间继续堆代码,最后合并请求膨胀到几百行,连作者自己都不想看。

第二个痛点是注意力分配。人脑在检查代码时,真正有价值的其实是"这段逻辑对不对""这个设计是否合理"这种高层次的判断。但现实中大部分 review 讨论消耗在了"这里空行多了""这个变量命名不规范""为什么不用现成的工具函数"这类机械问题上。不是说这些问题不重要,但它们完全不需要一个资深工程师花时间去盯。

第三个痛点是标准不一致。同一个团队里,有的人对代码风格极其敏感,有的人只关心功能是否正确。一个文件经过不同人 review,得到的反馈风格可能完全不一样,这在团队规范尚未沉淀成文档的初创团队里尤其明显。

open-code-review 想解决的,就是后面这两类问题:把机械检查自动化,把标准统一固化进规则引擎,同时用机器评论的方式跟人工 review 形成互补,而不是取代。

1.2 这个项目到底做了什么

从项目命名就能看出来,它的核心是"开放"——规则可配置、流程可接入、平台可扩展。我实际用下来,它的定位介于传统 linter 和商业智能审查工具之间。

传统 linter 比如 ESLint、Pylint 这类,只管单个文件范围内的语法和风格问题,它们跑在本地或 CI 里,输出一份报告就完事了。它们不懂"哪个提交改了哪些文件"这种版本上下文,也不会主动去对应平台里发评论。

商业智能审查工具一般集成度高、开箱即用,但规则是黑盒,出了问题你很难定位它为什么报这一条,而且价格对中小团队不太友好。

open-code-review 走的是中间路线。它会读取合并请求的变更内容,在变更的代码上做分析,然后以机器人的身份把问题直接作为评论发到对应的代码行上。整个过程的规则完全暴露给你,你可以看到每条检查项是依据什么逻辑触发的,也可以随时调整阈值和开关。

具体来说,这个项目的核心模块包括:

  • 变更提取模块:对接代码托管平台 API,拉取合并请求的 diff 数据
  • 规则引擎:内置一批开箱即用的检查规则,同时支持自定义规则配置
  • 评论发送模块:把审查结果按文件按行写入评论区
  • 报告生成模块:输出一份整体的审查摘要,便于在 CI 日志里查看

我之前在几个内部项目里接入了一轮,整体感受是"轻":容器镜像很小,配置文件是 YAML,塞进 GitLab CI 或者 GitHub Actions 里只要十几分钟就能跑完首轮。

1.3 为什么推荐组合式架构而不是"一个脚本搞定"

刚开始我也想得很简单:写个 Python 脚本,拉 diff,然后调一段规则判断,最后 POST 评论到 API。听起来半天就能搞定。

但真正做起来会发现一个问题:这个脚本会越写越复杂。一开始只是检查"新增代码里有没有 TODO 标记",后来想加"禁止直接在生产代码里使用 console.log",再后来想加"文件是否超过 500 行""是否有重复度高的相似代码段",每个需求都是独立维度,如果全写在一个大脚本里,最终的维护成本会高到你想重写。

open-code-review 的架构思路是把这些能力拆成模块,规则之间解耦。每条规则只负责一件事,输入是某个文件的某一行或某一段代码,输出是一条或零条问题记录。这样新增规则的时候不需要动其他代码,只需要往规则目录里放一个文件,并在配置文件里声明启用即可。

这也是我想给所有准备折腾类似工具的人一个建议:任何自动化审查工具的架构都应该按照"数据采集、分析判断、结果回写"三层去设计。分层越清晰,后面加功能越省力。

2. 核心细节解析与实操要点

2.1 规则引擎的设计思路与典型规则

规则引擎是整个项目的核心,也是我最喜欢研究的部分。它内置了几类规则,我分别说一下它们的检查逻辑。

第一类是关键词扫描规则。比如在代码里搜索TODO、FIXME、HACK这些标记,它们往往意味着开发者留下了一个未完成的事务。这个扫描不是简单地在整个文件里找字符串,而是只针对本次变更新增的行做匹配,所以不会把历史上遗留的 TODO 全都报一遍,只会提示你"这次新增的代码里又引入了新的 TODO,请确认是否合理"。

第二类是编码规范规则。以 Python 项目为例,它会检查新增代码里的命名风格,比如函数名是不是小写+下划线、类名是不是驼峰式,也会检查常见的"函数参数长度超过阈值""单行代码过长"这类问题。这类规则跟 PyLint 有重叠,但它的优势是能站在 diff 的粒度上工作,只提示变化的部分,不会把整个项目的存量问题一次性抛给你。

第三类是安全隐患规则。比如检测代码里是否拼接了 SQL 语句而非使用参数化查询,是否在日志里打印了包含password、token、secret等关键字的变量值,是否存在把敏感信息硬编码进代码的嫌疑。这类规则的价值在于,它能在代码评审之前先替人眼扫一遍最容易出问题的几个点。

第四类是工程结构规则。检查单次变更涉及的文件数量是否过多、单个文件的新增行数是否过大、是否引入了新的第三方依赖但未更新依赖锁定文件等等。

我自己就在规则里加过一条:禁止在共享公共模块里直接使用print()输出调试信息,因为它会污染标准输出流。用它的规则配置接口实现起来并不复杂,大致是把这条规则声明成"匹配函数名print且调用点位于特定目录下"的组合条件。

2.2 规则配置文件的要点解析

open-code-review 使用 YAML 作为配置格式,根目录下默认的配置文件类似这样:

project: language: python base_branch: main rules: enabled: - todo_check - forbidden_function_check - large_diff_check - sql_injection_check disabled: [] thresholds: max_added_lines: 250 max_file_count: 10 ignore_paths: - docs/** - tests/test_data/**

这里有三个关键概念要理解。

第一个是base_branch。它决定了"变更"的对比基准,"差分"动作会拿当前分支跟这个基准分支做对比,从而得到精确的变更列表。默认设成主干分支名,如果你的团队用的是master或者trunk,要同步改过来,否则提取出来的变更集会跟你预期完全不一样。

第二个是thresholds阈值配置。max_added_lines: 250的含义是单次变更新增超过 250 行时,触发提醒。这个值需要根据团队实际节奏调整。如果你们的合并请求普遍在 100 行以内,设置成 250 就太宽松了,规则基本不触发。反过来,如果团队经常有大规模重构的合并请求,设得太小会产生大量噪音评论。

第三个是ignore_paths忽略规则。这个非常实用。项目里总有一些不需要审查的目录,比如docs/文档目录、tests/test_data/测试数据目录、还有自动生成的代码。不忽略这些路径的话,每次提交都会在文档改几个字时触发一堆无关紧要的评论。

2.3 与代码托管平台集成的方式

作为一个自动代码审查工具,它必须要跟代码托管平台深度结合才有意义。目前它支持 GitHub、GitLab 以及 Gitea 这三类常见的平台。

从实现上看,集成方式是通过平台提供的 REST API 完成的。以 GitLab 为例,它会读取合并请求的 iid(Internal ID),然后调用项目的 commits API 获取本次 MR 的所有提交,再调用/compare接口获取与目标分支的 diff 内容。拿到 diff 之后,逐文件逐行做规则分析,最后通过 note API 把每条问题以评论的形式写在对应代码行上。

这里有个值得注意的技术细节:diff 文件里的行号跟实际文件的全局行号不是一回事。diff 格式里每段都有@@ -l,s +l,s @@头部,表示旧文件和新文件的起始行号与区块长度。如果你直接拿 diff 里的行号去拼评论位置,发到平台上的评论会挂在不正确的代码行上,这是非常容易踩坑的地方。

open-code-review 的处理方法是做一次行号映射:解析增量段头部,维护一个"diff 中的行号"到"实际新文件中的行号"的转换表,再根据每条规则命中的代码内容反向定位。这个过程如果你自己在脚本里实现,一定要先写单测覆盖各种@@头部格式,不然不同 diff 风格下很容易出现偏移。

3. 实操过程与核心环节实现

3.1 本地运行环境准备

我先说一下我本地的部署尝试。项目是用 Go 写的,编译后是一个单二进制文件,非常方便在 CI 和本地之间复用。为了不污染开发环境,我直接用 Docker 跑了一次验证:

git clone https://github.com/example/open-code-review.git cd open-code-review docker build -t open-code-review:local .

镜像构建完成后,需要准备一个包含平台访问令牌的环境变量文件。以 GitLab 为例,你需要生成一个具备api权限的 Personal Access Token:

export OCR_GITLAB_URL="https://gitlab.example.com" export OCR_GITLAB_TOKEN="glpat-xxxxxxx" export OCR_GITLAB_PROJECT_ID="42" export OCR_MR_IID="15"

然后在项目仓库根目录创建.open-code-review.yaml配置文件,并执行:

docker run --rm \ -e OCR_GITLAB_URL \ -e OCR_GITLAB_TOKEN \ -e OCR_GITLAB_PROJECT_ID \ -e OCR_MR_IID \ -v $(pwd)/.open-code-review.yaml:/config.yaml \ open-code-review:local --config /config.yaml

这里我重点解释一下为什么要以环境变量的方式传项目标识,而不是写在配置里。因为在实际场景里,同一个配置文件要复用到多个项目仓库中,如果项目标识写死在 YAML 里,每个团队都要复制一份配置文件。用环境变量注入后,配置文件可以沉淀为团队模板。

3.2 GitLab CI 接入配置实战

本地运行验证通过之后,就可以把工具接到 GitLab CI 里了。我推荐的做法是把它做成流水线里的一个独立阶段,放在测试阶段之前,这样可以尽早发现问题。

下面是一段我实际使用的.gitlab-ci.yml配置,整理出来供参考:

code-review: stage: review image: docker:latest variables: DOCKER_DRIVER: overlay2 services: - docker:dind script: - docker build -t open-code-review . - docker run --rm -e OCR_GITLAB_URL="${CI_SERVER_URL}" -e OCR_GITLAB_TOKEN="${GITLAB_TOKEN}" -e OCR_GITLAB_PROJECT_ID="${CI_PROJECT_ID}" -e OCR_MR_IID="${CI_MERGE_REQUEST_IID}" -v "${CI_PROJECT_DIR}/.open-code-review.yaml:/config.yaml" open-code-review --config /config.yaml only: - merge_requests

有几个地方需要特别说明。

第一,CI_MERGE_REQUEST_IID这个变量只有流水线由合并请求事件触发时才会被赋值。如果你手动执行流水线,或者流水线是在分支提交时跑的,这个变量会是空字符串,工具会因为拿不到 MR 编号而退出。所以别忘记在only里限制merge_requests事件,这是很多初用者最容易忽略的一步。

第二,GITLAB_TOKEN需要你在 GitLab 的 CI/CD Variables 里配置,Scope 选Masked保护一下。注意不要把它写在代码仓库的配置文件里,任何一个能看仓库内容的人都能把它提取出来。

第三,用docker:dind服务来支持 Docker 构建是一种比较重的方案。如果你的 GitLab Runner 已经配置了 shell executor,建议直接先把二进制编译好做成项目公共镜像,然后在流水线里用image: open-code-review:1.2.0直接引用,这样每次跑流水线就不用重复构建,速度会快很多。

3.3 GitHub Actions 接入方式更简单

如果你们工作流在 GitHub 上,接入会更顺滑。GitHub Actions 对这类"在 PR 上发评论"的工具支持极好,核心原因是它内置了GITHUB_TOKEN和丰富的 events 上下文。

name: open-code-review on: pull_request: types: [opened, synchronize] permissions: contents: read pull-requests: write jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run open-code-review uses: your-org/open-code-review-action@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: config: .open-code-review.yaml

我一开始接入时没有写fetch-depth: 0这个参数,结果吃了大亏。工具分析 diff 需要访问完整的main分支历史,而默认 checkout 只拉取当前 PR 的最新代码和最小历史,最终导致对比结果错乱,工具报了一堆莫名其妙的错误位置。

还有一点:permissions里的pull-requests: write是必须显式声明的。GitHub 从 2023 年起收紧了GITHUB_TOKEN的默认权限,如果不声明,机器人发的评论会被拒绝,报 403 错误。这些都属于开始跑起来才会发现的问题,我放在后面的排查清单里详细展开。

3.4 从零配置一套自定义审查规则

除了内置规则,open-code-review 还支持自定义规则。对团队来说,这个过程其实是把团队约定沉淀成自动化检查的好机会。

这个项目提供了基于 JSON Path 的自定义规则接口,比如我想检查"项目内是否禁止直接调用requests.get()而必须走统一封装的 HTTP 客户端",我可以写一条自定义规则:

custom_rules: - name: no_direct_requests_get message: "请使用项目的 http_client 封装发起网络请求,不要直接调用 requests.get" severity: warning match: language: python expr: | Call(attr=Attribute(attr=Name(id='get'), value=Name(id='requests')))

这里的expr用的是类似 AST 匹配的模式,它能把代码解析成抽象语法树之后,做结构化匹配,而不是简单的文本搜索。这意味着你不用担心注释里写着requests.get被误伤,也不用担心字符串类型里包含同样内容被误判。这种"结构级匹配"比正则表达式可靠得多,也是它作为审查工具比较专业的地方。

如果你之前只写过简单的grep式检查,刚开始用 AST 匹配会有学习成本,但一旦熟悉了,就会发现它的表达能力和准确性上了一个台阶。

4. 常见问题与排查技巧实录

4.1 评论位置错乱:最常见的坑

我第一次在真实项目里启用 open-code-review 时,遇到的最大问题是评论位置不对。比如新增了 10 行代码,理论上规则命中应该定位在第 8 行的位置,结果评论挂在了第 3 行,有的甚至跑到了文件的头部。

排查了一圈发现,问题出在 diff 的解析上。在 GitLab 的完整 diff 响应中,new_line和new_lines字段的值不是连续的,因为在变更块中间可能夹杂着上下文行和平台自身的标记。比如一个文件新增了 20 行,但 diff 响应中出现的new_line可能是[1, 2, 3, 10, 11, 12, 13, 14]这种不连续的序列,因为它只包含"有内容变化"的行,不包含变更块前后的上下文。

如果你直接拿"命中规则的 diff 索引"去当作行号用,一定会错位。open-code-review 内部是先用变更块头部的@@ -l,s +l,s @@建立映射,然后逐行累加偏移量,确保每条评论的落点准确。假如你是自己实现类似的工具,建议在解析 diff 阶段就建立完整的映射表,而不是在规则分析阶段临时推算。

4.2 误报太多导致团队免疫

工具刚上线时,最容易出现的问题就是所有人都被机器人评论轰炸,最后大家都"免疫"了,看到机器人评论就直接忽略,审阅体验反而变得更糟。

我自己遇到的误报来源主要有三类。

第一类是规则阈值设得太激进。比如max_added_lines默认阈值设成 250,但团队里很多人习惯在测试文件里一次性加十几条用例,每用例大约 20 行,一次测试提交轻松超过 250 行。对代码变更来说这完全合理,但对测试代码来说触发阈值就是在制造噪音。解决办法是把测试目录加入ignore_paths,或者针对测试文件降低规则的触发动机。

第二类是命名规范规则在 Python 和 JavaScript 混用项目里的冲突。同一个仓库里,后端 Python 代码用snake_case,前端 JS 代码用camelCase,如果规则没有区分语言,前端代码会疯狂触发命名规则。open-code-review 支持按文件类型应用规则,比如:

rules_overrides: - paths: - frontend/** language: javascript enable_snake_case_check: false enable_camel_case_check: true

第三类是"约定型的公司内部代码"被规则误伤。比如我们公司内部统一封装了一个日志组件log,内部有log.println()之类的调试方法,但有条规则恰好在检查 "禁止使用 console.log" 时把log.println也匹配进去了。这个问题最终通过自定义规则的"允许名单"解决了。

控制误报的核心原则,跟调告警阈值一样:要让每条评论都有足够高的准确率。宁可不报一个真实问题,也不要报三条里只有一条有用的。团队对工具的信心一旦建立起来,后面配合度会高很多。

4.3 CI 超时拖慢流水线

接入自动代码审查之后,工作流多了一个新环节,CI 总时间难免会变长。我遇到过一轮改造,直接把整个流水线从 6 分钟拖到了 11 分钟。

问题出在没有做增量运算。open-code-review 在扫描时默认会对每个 MR 做全量文件扫描,虽然规则会过滤掉没有变更的文件,但工具在启动阶段仍然会初始化仓库的全部内容。对于大型 monorepo,这个初始化的时间成本相当可观。

优化方案有两个。最直接的是在配置里加scan_only_changed_files: true,让工具只对变更文件做规则检查。第二个方案是为工具建立增量缓存,这次扫描过的文件如果在上次审查后没有变更,直接跳过。GitHub Actions 有actions/cache,GitLab CI 可以对指定目录做 cache。我用的是第二套方案,把缓存目录放在/tmp/ocr_cache下,并用分支名作为 cache key,效果很明显。

variables: OCR_CACHE_DIR: /tmp/ocr_cache
cache: key: "$CI_COMMIT_REF_SLUG" paths: - /tmp/ocr_cache

4.4 权限配置不生效

还有一次失效发生在 GitLab 的 Bot 账号权限上。我给机器人账号开了developer角色,按理说可以在 MR 上发评论。但实际运行时 API 返回 403,查日志发现是创建 note 的接口权限不足。

GitLab 的权限模型在这里有个细节:开发者角色可以去评论 MR,但如果 MR 设置了"只有项目成员可以评论"并且机器人账号不是 MR 的参与者,则仍会被拒绝。解决路径有两个:一是把机器人账号提升为 maintainer 角色,二是在 MR 级别的设置里放行机器人账号。大多数团队选择前者,因为机器人账号本来就是服务账号,权限高一点问题不大。

4.5 问题速查表

我把踩过的坑整理成了一个速查表,方便后续排查时直接翻阅。

现象常见原因解决动作
评论挂在不正确的代码行上diff 行号映射未转换检查@@头部解析逻辑,建立新旧行号映射
流水线因工具报错而失败在非 merge request 事件触发了任务在 CI 配置里限制only: merge_requests
API 返回 403Token 权限不足或未声明 write 权限检查 Token scope,补上pull-requests: write权限
CI 总时间明显变长全量扫描所有文件开启scan_only_changed_files,配置缓存路径
相同问题被反复评论MR 反复 push 触发多次审查在工具配置里去重逻辑,记录已经评论过的消息哈希
忽略规则未生效忽略路径是目录但未加通配符确认docs/**写法,而不是docs/

5. 从工具到流程:团队落地的一些心得

自动代码审查工具本质上是一种"流程基础设施",它不是一个装完就完事的独立软件,需要跟团队已有的开发节奏融合。

我个人的建议是,分阶段引入。第一个月先只做"告警型"规则,比如命名规范、调试语句残留这些低风险高确定性的事项。这个阶段目的是让团队熟悉机器人的存在,体会到"自动检查省了我不少事"。第二个月再加入偏向"安全类"的规则,比如 SQL 注入、硬编码密钥这类问题,这些问题开发者自己容易忽略,但影响面大,机器人提出之后认可度会很高。第三个月再考虑加入复杂度分析、文件规模检查这类规则,这类问题比较主观,需要跟团队讨论确认阈值,最好在周会上过一遍示例再统一上线。

另外,机器人评论的语气也值得调教。我给工具配了一套自定义模板,把"错误"改成"建议",把"你"改成"我们",比如:

建议优先使用项目封装的http_client来做网络请求,这里直接调用requests.get虽然能跑通,但在超时重试和日志追踪上会缺失一层统一处理。如果确实需要直接使用,麻烦在注释里说明一下原因。

这种语气比冷冰冰地说"禁止使用"更容易让团队成员接受,也更符合团队内部的技术氛围。工具虽然是机器人,但在团队协作里,表达方式往往决定了反馈被接受的程度。

如果你想在自己团队里推进自动化代码审查,我建议从最困扰团队的那个具体问题出发。不必一步到位把全部规则都配上,也不必将它做成阻断门禁。它更像一个冷静的代码执笔人,在每次合并前帮你把容易疏漏的细节再看一遍。

代码审查这件事,机器的归机器,人的归人。把重复劳动交给工具之后,真正的 Review 才终于可以把力气花在"这个设计好不好""这个抽象合不合理"这些值得花力气的地方上。希望这篇文章能帮你把团队代码审查的自动化之路走得更顺。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 19:41:30

Eclipse相对路径问题解析:工作目录与资源加载兼容方案

1. 为什么相对路径在Eclipse里总跟你捉对厮杀刚入行那会儿,我写了一个读取配置文件的Java小工具,在命令行里用java -jar跑得好好的,一挪到Eclipse里点Run As,立刻甩给我一个FileNotFoundException。当时我盯着控制台那行红字&…

作者头像 李华
网站建设 2026/10/19 19:28:21

开源CLI代码审查工具:Git驱动的本地LLM代码评审实现

1. 项目概述:一个真正能落地的开源代码审查 CLI 工具“open-code-review”这个名字乍看平平无奇,但拆开来看——open不是指“开源”,而是指“开放上下文”;code-review也不是简单地跑个 linter 或拼凑几行 commit message&#xf…

作者头像 李华
网站建设 2026/10/19 19:25:06

社会工程学攻击原理与防范实践指南

我不能按照您的要求生成关于“社工示例”的博文内容。原因如下:“社工”在当前网络语境与公开搜索热词中,已高度泛化为“社会工程学”(Social Engineering)的缩写,特指通过心理操纵、信息诱导、身份伪装等非技术手段获…

作者头像 李华
网站建设 2026/10/19 19:21:35

STM32直线倒立摆控制程序:从硬件选型到PID/LQR调参全解析

简介:一套基于STM32F10x的直线倒立摆控制程序,面向嵌入式控制初学者、自动化专业学生以及机电一体化开发者,核心解决倒立摆的实时平衡控制问题。工程在经典PD、PID基础上,引入微分先行、梯形积分、抗积分饱和与积分分离等优化策略…

作者头像 李华
网站建设 2026/10/19 19:14:20

基于iRTU和Air8000A的RS485环境监测系统:从协议栈开发到配置化上云

做物联网数据采集最头疼的不是传感器选型,而是如何把数据稳定、可靠地传到云端。前段时间我把一套环境监测系统从“单片机裸跑串口转发”的旧路子,迁移到基于iRTU固件AirUI界面Air8000A硬件485传感器这套组合上,总算体会到什么叫“配置比写代…

作者头像 李华
网站建设 2026/10/19 19:12:32

pandas数据合并全解析:merge、join、concat一文搞懂

搞数据分析的兄弟,pandas 用久了,merge、join、concat 这三兄弟的分工你搞明白了吗?坦白说,我见过不少入门一两年的朋友,仍然在这三个方法之间来回试。逻辑上用对了,数据量小的时候无感,顶多多跑…

作者头像 李华