必须用 pip-licenses 加自定义脚本硬性拦截:导出 licenses.json 后校验每个包 license 是否在白名单内,空值或 unknown 也拒付;注意 git/本地依赖漏检、版本差异导致 license 变更、setuptools 插件识别异常三类坑。

Python 项目 CI 中如何强制检查第三方 license
CI 流程里加一道 license 检查 gate,不是“可选提醒”,而是“不合规就拒付合并”——这事得靠工具链卡死,不能靠人眼扫 requirements.txt。
用 pip-licenses + 自定义脚本做硬性拦截
pip-licenses 是最轻量、兼容性最好的选择,它能从当前环境导出所有依赖的 license 文本和类型,但默认不校验合规性。必须自己补一层判断逻辑。
- 先用
pip install pip-licenses安装,再在 CI 脚本里跑:pip-licenses --format=json --output=licenses.json --format=markdown --output=licenses.md - 关键在后续解析:读取
licenses.json,遍历每个包的license字段(注意是字符串,可能含多个 license 或模糊表述如"MIT or Apache-2.0") - 只允许白名单中的 license,比如只认
"MIT"、"Apache-2.0"、"BSD-3-Clause";遇到"GPL-3.0"、"AGPL-3.0"、"CC-BY-NC-4.0"直接 exit 1 - 特别注意
license字段为空或为"UNKNOWN"的包——这不算“没 license”,而是“无法确认”,也该拦住
为什么不用 pip-audit 或 pip-show-licenses
pip-audit 只查漏洞,不查 license;pip-show-licenses 已多年未维护,对现代 PEP 517 构建的包支持差,常漏掉 pyproject.toml 里声明的依赖。
-
pip-licenses能正确处理pip install -e .和pip install .[dev]场景下的 extras 依赖 - 它读的是已安装包的
dist-info/LICENSE或PKG-INFO,比单纯解析requirements.txt更真实 - 但要注意:某些包(如
numpy)把 license 放在顶层目录而非dist-info,pip-licenses默认会跳过——得加参数--include-optional并配合--format=markdown手动 fallback
容易被忽略的三个实际坑
license 检查 gate 看似简单,线上翻车基本都栽在这三处。
立即学习“Python免费学习笔记(深入)”;
- CI 环境里用的是
pip install -r requirements.txt,但pip-licenses读的是当前 site-packages ——如果 requirements 里有git+https或本地路径依赖,它们可能根本没进 site-packages,导致漏检 - 同一个包不同版本 license 可能不同(如
requests 是 Apache-2.0,<code>>=2.28.0加了额外条款),仅靠包名匹配白名单不够,必须带版本号校验 -
pip-licenses对setuptools插件类依赖(比如pydantic的pydantic-core)识别不稳定,有时会标成"UNKNOWN"却不报错——得在脚本里主动 grep 日志里有没有"WARNING: Unable to find license"
真正卡住 gate 的,从来不是“有没有 license”,而是“能不能确定它是你准许的那一个”。别信元数据字段,要信你亲手验证过的文本内容和上下文。










