開発者のためのSPDX実用編: pip-licensesでTransformersの依存ライセンスを確認する
PredNextの永井です。前回の記事では、SPDXライセンス識別子や式構文(AND/OR/WITH)の仕組みを紹介し、PEP 639への移行が進む中でもライセンス表記のばらつきが残る現状に触れました。
今回は Hugging Face Transformers を題材に、pip-licenses を使った依存ライセンスの確認を一通り試します。「一覧の把握」「禁止ライセンスのブロック」「許可リストによる制限」という3つのニーズに対してpip-licensesでどう対応できるかを紹介しつつ、表記ゆれやプラットフォーム差異の問題にも触れます。
セットアップ
今回は uv を使い、transformers[torch] を依存に持つプロジェクトを作成しました。
uv init hf-license-check --python 3.12
cd hf-license-check
uv add 'transformers[torch]' pip-licenses
Transformers の依存ライセンスを確認する
uv run pip-licenses で、インストール済みパッケージのライセンスを一覧表示できます。出力フォーマットは -f オプションで markdown、json、csv などに変更でき、--with-urls でパッケージURLを、--with-license-file でライセンス全文も出力に含められます。ライセンス情報をまとめて提出する場合に役立ちます。
今回セットアップした transformers[torch] 環境のライセンス状況を、macOS(Python 3.12.7、pip-licenses 5.5.1)で確認し、ライセンスファミリーごとに集計した結果は次の通りです。
| ファミリー | 件数 |
|---|---|
| BSD 系 | 15 |
| MIT 系 | 9 |
| Apache 系 | 7 |
| MPL 系 | 2 |
| ISC | 1 |
| PSF | 1 |
35パッケージのうち、GPL系ライセンスは0件、UNKNOWNも0件でした。すべてpermissive(寛容)なオープンソースライセンスです。
全35パッケージの一覧(クリックで展開)
| Name | Version | License |
|---|---|---|
| Jinja2 | 3.1.6 | BSD License |
| MarkupSafe | 3.0.3 | BSD-3-Clause |
| PyYAML | 6.0.3 | MIT License |
| Pygments | 2.19.2 | BSD License |
| accelerate | 1.13.0 | Apache Software License |
| annotated-doc | 0.0.4 | MIT |
| anyio | 4.12.1 | MIT |
| certifi | 2026.2.25 | Mozilla Public License 2.0 (MPL 2.0) |
| click | 8.3.1 | BSD-3-Clause |
| filelock | 3.25.1 | MIT |
| fsspec | 2026.2.0 | BSD-3-Clause |
| h11 | 0.16.0 | MIT License |
| hf-xet | 1.3.2 | Apache-2.0 |
| httpcore | 1.0.9 | BSD-3-Clause |
| httpx | 0.28.1 | BSD License |
| huggingface_hub | 1.6.0 | Apache Software License |
| idna | 3.11 | BSD-3-Clause |
| markdown-it-py | 4.0.0 | MIT License |
| mdurl | 0.1.2 | MIT License |
| mpmath | 1.3.0 | BSD License |
| networkx | 3.6.1 | BSD-3-Clause |
| numpy | 2.4.3 | BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0 |
| packaging | 26.0 | Apache-2.0 OR BSD-2-Clause |
| psutil | 7.2.2 | BSD-3-Clause |
| regex | 2026.2.28 | Apache-2.0 AND CNRI-Python |
| rich | 14.3.3 | MIT License |
| safetensors | 0.7.0 | Apache Software License |
| shellingham | 1.5.4 | ISC License (ISCL) |
| sympy | 1.14.0 | BSD License |
| tokenizers | 0.22.2 | Apache Software License |
| torch | 2.10.0 | BSD-3-Clause |
| tqdm | 4.67.3 | MPL-2.0 AND MIT |
| transformers | 5.3.0 | Apache 2.0 License |
| typer | 0.24.1 | MIT |
| typing_extensions | 4.15.0 | PSF-2.0 |
ライセンスの表記ゆれ
一覧を見ると、同じライセンスに対して複数の表記が混在していることがわかります。たとえばMITライセンスには「MIT License」と「MIT」、BSDライセンスには「BSD License」と「BSD-3-Clause」、Apacheライセンスには「Apache Software License」「Apache 2.0 License」「Apache-2.0」があります。
この表記ゆれは、PEP 639 への移行が進む過渡期の問題です。PEP 639 により、Pythonパッケージのライセンスメタデータは SPDX 式の License-Expression で記述する方向に移行が進んでいますが、2026年現在、従来の Classifier ベースの表記が残っているパッケージも多くあります。
この表記ゆれは、次のセクションで紹介するポリシーチェックに影響します。
pip-licenses でポリシーチェックする
pip-licensesには、ライセンスを自動で検証するためのオプションがあります。ここでは、よくある3つのニーズに対してpip-licensesでどう対応できるかを見ていきます。
ニーズ1:依存のライセンスをレポートにまとめたい
pip-licenses の基本機能で依存パッケージのライセンス一覧を取得できます。オプションを使えば、第三者への提出用レポートやSBOM作成の素材にも役立ちます。
uv run pip-licenses -f markdown --with-urls --with-license-file \
--output-file=license-report.md
ニーズ2:GPLなどのcopyleftライセンスをブロックしたい(ブラックリスト)
商用プロジェクトで最も多いニーズは、GPL・AGPL等のcopyleftライセンスが依存に含まれていないことの確認でしょう。--fail-on と --partial-match を組み合わせると、指定したライセンスが見つかった時点でエラー(終了コード1)にできます。
uv run pip-licenses --fail-on="GPL;AGPL;LGPL" --partial-match
--partial-match は部分文字列マッチを有効にするオプションです。GPL という文字列が GNU General Public License v3.0 にも GPL-3.0-only にもマッチするため、表記ゆれがあってもおおよそライセンスファミリー単位でブロックできます。
今回のTransformersの依存にはGPL系ライセンスが含まれていないため、このチェックは問題なくパスします。CIに組み込む場合も、このブロックリスト方式が最もシンプルで壊れにくいアプローチです。
ニーズ3:許可したライセンスだけに制限したい(ホワイトリスト)
より厳密なポリシー管理が必要な場合は、--allow-only で許可するライセンスのリストを指定し、それ以外が含まれていればエラーにできます。
ただし、--allow-only はデフォルトで文字列の完全一致でチェックするため、表記ゆれとSPDX複合式の両方に対応する必要があります。例えば、Apache-2.0 と CNRI-Python を個別に許可していても、Apache-2.0 AND CNRI-Python という文字列全体が許可リストになければ通りません。今回の依存には以下の複合式があります。
| パッケージ | ライセンス式 | 意味 |
|---|---|---|
| numpy | BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0 | コード部分ごとに5つのライセンスが適用される |
| packaging | Apache-2.0 OR BSD-2-Clause | 利用者がどちらかを選択できるデュアルライセンス |
| regex | Apache-2.0 AND CNRI-Python | 2つのライセンスが同時に適用される |
| tqdm | MPL-2.0 AND MIT | MPL-2.0とMITの両方が適用される |
表記ゆれと複合式の両方を考慮した許可リストで実行します。
uv run pip-licenses \
--allow-only="MIT;BSD-3-Clause;Apache-2.0;ISC;PSF-2.0;0BSD;Zlib;CC0-1.0;CNRI-Python;\
MIT License;BSD License;Apache Software License;Apache 2.0 License;\
ISC License (ISCL);Mozilla Public License 2.0 (MPL 2.0);MPL-2.0;\
Apache-2.0 AND CNRI-Python;Apache-2.0 OR BSD-2-Clause;\
BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0;MPL-2.0 AND MIT"
これで全35パッケージがパスします。ただし、依存パッケージがSPDX式に移行したり新しいライセンス表記が追加されるたびにリストの更新が必要になるため、メンテナンスコストは高くなります。--partial-match を --allow-only と組み合わせればリストを簡略化できますが、意図しないマッチのリスクもあるため、用途に応じて使い分けてください。
プラットフォームで結果が異なる
同じパッケージでも、プラットフォームによってライセンス構成は変わります。ここまでの結果はすべてmacOS上のものだったため、Dockerを使ってLinux環境でも同じ transformers[torch] をインストールし、pip-licensesを実行してみました。
Linux x86_64では、PyTorchの依存としてNVIDIA CUDAパッケージが16個追加でインストールされます。macOSでは全35パッケージがpermissiveなオープンソースライセンスでしたが、Linux x86_64では53パッケージ中16件(約30%)がプロプライエタリライセンスになります。
また、この16個のNVIDIAパッケージのライセンス表記も4種類に分かれています。
| 表記 | 件数 | 例 |
|---|---|---|
Other/Proprietary License | 13 | nvidia-cublas-cu12 等 |
NVIDIA Proprietary Software | 1 | nvidia-cusparselt-cu12 |
LicenseRef-NVIDIA-Proprietary | 1 | nvidia-nvshmem-cu12 |
LicenseRef-NVIDIA-SOFTWARE-LICENSE | 1 | cuda-bindings |
プロプライエタリライセンスにはSPDXの標準識別子が存在しないため、パッケージごとに異なる LicenseRef- 識別子が定義されています。上記16パッケージはすべて同じNVIDIA CUDA EULAに基づきますが、Classifierベース、旧メタデータ、SPDX LicenseRefの3方式が混在しています。
ライセンスチェックはデプロイ先と同じプラットフォームで実行するのが確実です。
GitHub Actions での自動化
CIにライセンスチェックを組み込む方法を紹介します。以下は、pyproject.toml や uv.lock に変更があった際に自動でライセンスチェックを実行する設定例です。ここでは、シンプルで壊れにくいブラックリスト(--fail-on)方式を採用しています。
GitHub Actions のワークフロー例(クリックで展開)
name: License Check
on:
pull_request:
paths:
- 'pyproject.toml'
- 'uv.lock'
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
- name: Install dependencies
run: uv sync
- name: Check licenses
run: |
uv run pip-licenses \
--fail-on="GPL;AGPL;LGPL;EUPL;SSPL" \
--partial-match
- name: Generate license report
if: always()
run: uv run pip-licenses -f markdown --with-urls > license-report.md
- name: Upload license report
if: always()
uses: actions/upload-artifact@v4
with:
name: license-report
path: license-report.md
何も設定しなければCIは ubuntu-latest(Linux x86_64)で動くため、前のセクションで見たとおりNVIDIA CUDAパッケージなどが追加される可能性があります。プロプライエタリライセンスのパッケージを許容する場合はそのまま、除外したい場合は --fail-on にライセンス表記を追加するか、--ignore-packages で特定パッケージを除外してください。より厳密に --allow-only で管理する場合は、前述の表記ゆれ・複合式への対応が必要です。
pip-licenses 以外のツール
pip-licensesはPythonのパッケージメタデータのみを対象としています。コンテナイメージを配布する場合は、イメージ全体のファイルシステムをスキャンできるツールが有用です。ここでは syft(Anchore社のSBOMジェネレータ)と trivy(Aqua Security社のセキュリティスキャナ)を使い、前述のDockerイメージをスキャンした結果を比較します。
3ツールの比較概要
| 項目 | pip-licenses | syft | trivy |
|---|---|---|---|
| アプローチ | Python メタデータ参照 | イメージ全体をスキャン → SBOM 生成 | イメージ全体をスキャン → ライセンス分類 |
| Python パッケージ検出数 | 53 | 70 | 70 |
| OS パッケージ検出 | 不可 | 可能(173パッケージ) | 可能(624ライセンスエントリ) |
| ライセンス表記 | Classifier / SPDX 混在そのまま | SPDX 識別子に正規化(一部 LicenseRef) | SPDX 識別子に正規化 |
| 重大度分類 | なし | なし | あり(notice / reciprocal / restricted) |
Pythonパッケージの検出数に差があるのは、ツールの検出対象が異なるためです。Dockerイメージ内で pip list に登録されているパッケージは58件です。pip-licensesはここからシステムパッケージ(pip、setuptools)と自身の依存(pip-licenses、prettytable、wcwidth)の計5件をデフォルトで除外するため、53件になります。syft・trivyはファイルシステムを直接スキャンし、setuptools内部のvendoredパッケージ12件も検出するため70件になります。
ライセンス表記の正規化
syft・trivyはライセンス表記をSPDX識別子に正規化します。pip-licensesとの比較を以下に示します。
| パッケージ | pip-licenses | syft | trivy |
|---|---|---|---|
| PyYAML | MIT License | MIT | MIT |
| Pygments | BSD License | BSD-2-Clause | BSD-3-Clause |
| httpx | BSD License | BSD-3-Clause | BSD-3-Clause |
| Jinja2 | BSD License | NOASSERTION | BSD-3-Clause |
| accelerate | Apache Software License | LicenseRef-Apache | Apache-2.0 |
| transformers | Apache 2.0 License | LicenseRef-Apache-2.0-License | Apache-2.0 |
| certifi | Mozilla Public License 2.0 (MPL 2.0) | MPL-2.0 | MPL-2.0 |
trivyは正規化の一貫性に優れ、Classifierベースの Apache Software License → Apache-2.0 のようにSPDX識別子へ変換しています。syftは一部を LicenseRef-* にフォールバックする傾向があり、Jinja2では NOASSERTION になるケースもありました。
ただし、正規化が常に正確とは限りません。上の表でPygmentsはtrivyが BSD-3-Clause、syftが BSD-2-Clause と判定していますが、Pygmentsの実際のライセンスはBSD-2-Clauseであり、syftのほうが正確です。trivyは BSD License を一律に BSD-3-Clause へ変換する傾向があります。
NVIDIAパッケージではさらに大きな差異が見られます。たとえばnvidia-nccl-cu12は、pip-licenses・trivyでは Other/Proprietary License ですが、syftは BSD-3-Clause と報告します。NCCLのソースコードは実際にはApache-2.0(一部BSD)で公開されており、いずれのツールも正確ではありません。NVIDIA CUDA関連パッケージのライセンスは複雑なため、個別確認を推奨します。
このように、同じパッケージでもツールによって判定結果が食い違うことがあります。単一ツールの出力を鵜呑みにせず、クロスチェックやライセンス原文の確認が必要です。
trivy の重大度分類
trivyはライセンスをカテゴリと重大度で自動分類するため、ポリシー設計に直接活用できます。
| カテゴリ | 重大度 | 該当ライセンス例 |
|---|---|---|
| notice | LOW | MIT, BSD-3-Clause, Apache-2.0, ISC 等 |
| reciprocal | MEDIUM | MPL-2.0(certifi, tqdm) |
| restricted | HIGH | LGPL-3.0-only(autocommand) |
| unknown | UNKNOWN | NVIDIA プロプライエタリ, PSF-2.0 等 |
pip-licenses では見えない vendored パッケージ
pip-licensesでは検出できないLGPLv3パッケージが、syft・trivyで発見されました。setuptoolsの _vendor/ ディレクトリにvendoringされた autocommand です(syft: LicenseRef-LGPLv3、trivy: LGPL-3.0-only、重大度: HIGH)。
transformers[torch]
└→ torch
└→ setuptools (Python 3.12以上で必須依存)
└→ _vendor/autocommand (vendored, LGPLv3)
vendoredパッケージは pip list に現れないため、pip-licensesの --fail-on="GPL;AGPL;LGPL" でも検出できません。setuptoolsがvendoringしている12件のうち、autocommandだけがLGPLv3(コピーレフト系)です。
autocommandは実行時には読み込まれません。importしているのはsetuptools内部の開発支援ユーティリティのみで、transformers / torchのワークフローとは無関係です。ただし、コンテナイメージへの同梱が「配布」に該当するかは解釈が分かれうるため、厳格なライセンス監査では指摘対象になりえます。
OS レベルのライセンス
コンテナイメージの配布では、OSパッケージのライセンスも考慮が必要です。trivyはコンテナ内のDebianパッケージ(bash, coreutils, tar等)もスキャンし、624件のライセンスエントリを報告しました。Pythonパッケージだけでは「GPLなし」でも、OSパッケージにはGPL-2.0 / GPL-3.0が多数含まれています。
ツールの使い分け
| 目的 | 推奨ツール | 理由 |
|---|---|---|
| 開発時のライセンス確認 | pip-licenses | pipの依存ツリーに沿った見やすい出力。CIに組み込みやすい |
| コンテナイメージの配布 | syft / trivy | 物理的に同梱される全ファイルのライセンスを網羅 |
| ライセンス監査・コンプライアンス | 複数ツールの併用 | pip-licensesだけではvendoredパッケージを見落とす |
まとめ
pip-licensesを使えば、Pythonプロジェクトの依存ライセンスを手軽に一覧できます。ポリシーチェックの方法はニーズに応じて選べます。
- レポート生成(
-f markdown --with-urls):依存ライセンスを把握する - 禁止ライセンスのブロック(
--fail-on+--partial-match):GPL等のcopyleftを排除したい場合に最もシンプルで壊れにくい - 許可リストによる制限(
--allow-only):最も厳密だが、表記ゆれやSPDX複合式への対応が必要でメンテナンスコストが高い
依存ライセンスの管理には、以下の点に注意してください。
- 表記ゆれ:ClassifierベースとSPDX式の混在により、同じライセンスに複数の表記がある
- プラットフォーム差異:プラットフォームによりライセンス構成も変わるため、デプロイ先と同じ環境でチェックすべき
- vendoredパッケージ:pip-licensesでは検出できないvendoredパッケージが存在する。コンテナ配布時はsyft・trivyの併用が有効
pip install の1行にどれだけのライセンスが関わっているかをまず把握し、そこからライセンス管理を始めてみましょう。
お仕事募集中です
PredNextでは現在、お仕事のご依頼を募集しています。自然言語処理や画像処理などのAI技術が得意で、特に軽量化・高速化を強みにしています。ご興味のある方はお問い合わせフォームからご連絡ください。