pipの非推奨機能を回避せよ:将来を見据えた依存関係管理のための『PEP 621』完全対応マニュアル
こんにちは。開発環境アーキテクトの私だ。これまで数千のプロジェクトのCI/CDパイプラインや、巨大なモノリス・マイクロサービスのビルドシステムを監査・構築してきた。
その中で、未だに多くの現場で見かけるのが、レガシーな `setup.py` や手動メンテナンスの `requirements.txt`、そしてカオスと化した依存関係の迷宮だ。「`setup.py test` は何年も前に非推奨だ」「`pip install` の実行時に任意のコードが走る `setup.py` はセキュリティ上の致命傷になり得る」——この事実を、まだ腹落ちしていないエンジニアが多すぎる。
Pythonエコシステムは、PEP 621(メタデータの標準化)の登場によって完全に生まれ変わった。本稿では、レガシーな依存関係管理を根絶し、現代の超高速パッケージマネージャーである `pip`、`Poetry`、そしてRust製モンスターツール `uv` のすべてをシームレスに串刺しにする、『PEP 621完全準拠プロジェクト構成』の極意を叩き込む。
—
1. なぜ `setup.py` と `requirements.txt` は捨て去られるべきなのか
アーキテクトの視点から言えば、`setup.py` は「ビルドスクリプト」ではなく「ただの任意のPythonコード実行メカニズム」に過ぎなかった。これが何を意味するか?
`pip install` を実行した瞬間、ターゲット環境上で任意のスクリプトがブラックボックスとして実行される。これはSupply Chain Attack(サプライチェーン攻撃)の温床であり、コンテナビルドにおけるキャッシュ効率も最悪だった。
一方、`requirements.txt` はロックファイルとしては機能するものの、パッケージとしてのメタデータ(依存関係の方向性、エントリーポイント、ライセンス)を持たないため、ライブラリ開発とアプリケーション開発の境界を曖昧にし、依存関係解決のアルゴリズムに一貫性を欠かせてきた。
PEP 621がもたらすパラダイムシフト
Pythonの標準化団体(PyCPA)が定めた PEP 621 は、`pyproject.toml` の中にプロジェクトのメタデータを宣言的に記述する標準仕様を定義した。
- 完全な宣言型(Declarative): コードではなくデータ(TOML)として記述するため、静的解析が容易であり、セキュリティリスクがゼロになる。
- ツール非依存(Tool-agnostic): `pip` であろうが、`Poetry` であろうが、`uv` であろうが、ビルドバックエンド(PEP 517)さえ共通化していれば、メタデータを一元的に解釈できる。
つまり、どのツールに乗り換えても、`pyproject.toml` のコア部分を書き換える必要がない状態 を構築することこそが、現代のDevOpsにおける最大の保険となるのだ。
—
2. 実践:PEP 621完全準拠 `pyproject.toml` の設計
それでは、実際にプロダクション環境で耐えうる最高峰の `pyproject.toml` を構築しよう。ここではビルドバックエンドに `hatchling` を採用する。軽量かつ拡張性が高く、現代の標準として最も手堅い選択肢だ。
[build-system]
PEP 517に準拠したビルドバックエンドの指定。setup.pyの実行は二度と行わない。
requires = [“hatchling>=1.21.0”]
build-backend = “hatchling.build”
[project]
PEP 621準拠のプロジェクトメタデータ核心部
name = “enterprise-core-engine”
version = “2.4.0”
description = “Mission-critical backend processing engine with ultra-low latency.”
readme = “README.md”
requires-python = “>=3.11”
license = { text = “Proprietary” }
authors = [
{ name = “DevOps Architecture Team”, email = “arch-team@example.com” }
]
classifiers = [
“Private :: Do Not Upload”,
“Programming Language :: Python :: 3.11”,
“Programming Language :: Python :: 3.12”,
“Topic :: Software Development :: Libraries :: Application Frameworks”,
]
本番稼働に必須のランタイム依存関係
dependencies = [
“pydantic>=2.6.0,<3.0",
"fastapi>=0.110.0″,
“uvicorn[standard]>=0.27.0”,
“sqlalchemy>=2.0.25”,
“asyncpg>=0.29.0”,
]
[project.optional-dependencies]
開発・テスト環境用のオプショナル依存関係(Poetryやuvでも共通解釈される)
dev = [
“pytest>=8.0.0”,
“pytest-asyncio>=0.23.5”,
“ruff>=0.2.1”,
“mypy>=1.8.0”,
“httpx>=0.26.0”, # TestClient用
]
[project.scripts]
CLIエントリーポイントの定義(setup.pyの entry_points と同等)
core-cli = “enterprise_engine.cli:main”
[tool.hatch.build.targets.wheel]
ビルド対象パッケージの明示的指定
packages = [“src/enterprise_engine”]
この構成の美しさは、「誰が・どのツールでビルドしても結果が完全に再現される」点にある。
—
3. ツール別実装:pip, Poetry, uv のスマートな使い分け
アーキテクトとして特筆すべきは、これらのツールがPEP 621およびPEP 517をどのように解釈し、我々のワークフローをどう加速させるかだ。
A. `pip` + `build` (軽量・標準重視のミニマリスト環境)
CI/CDの軽量コンテナや、余計な依存関係を入れたくない環境では、素の `pip` と `build` コマンドを使用する。
1. 仮想環境の作成
python -m venv .venv
source .venv/bin/activate
2. 開発モード(editable install)でのインストール(PEP 621 / PEP 660準拠)
-e オプションにより、ソースコードの変更が即座に反映される
pip install –upgrade pip
pip install -e “.[dev]”
3. 配布用ホイール(.whl)およびソース配布物のビルド
pip install build
python -m build –sdist –wheel
B. `Poetry` (エンタープライズ・厳格なロックファイル管理)
Poetryは、PEP 621をネイティブサポートしつつ、独自の高度な依存関係解決エンジンとロックファイル (`poetry.lock`) を提供する。
Poetryを使用する場合でも、メタデータは `pyproject.toml` の `[project]` セクション(PEP 621)に記述し、Poetry特有の設定は `[tool.poetry]` に分離することで、将来的な他ツールへの移行性を担保できる。
Poetry固有の設定(ビルドバックエンドをPoetryのものに変更する場合)
[build-system]
requires = [“poetry-core>=1.9.0”]
build-backend = “poetry.core.masonry.api”
[tool.poetry]
Poetry専用の追加設定(パッケージの構成など)
packages = [{ include = “enterprise_engine”, from = “src” }]
※ [project] セクション(PEP 621)はそのまま併用可能、あるいはPoetryが自動同期する
Poetryでの依存関係の同期(ロックファイルに基づいた厳密なインストール)
poetry install –with dev
C. `uv` (圧倒的な速度を誇る次世代Rust製ツール)
現在、DevOps界隈で最も熱い視線を注がれているのが、Astral社が開発した `uv` だ。内部アーキテクチャとしてRustによる並行処理とキャッシュ機構を極限まで最適化しており、`pip` の数十倍〜100倍近い速度で依存関係を解決・インストールする。
`uv` は、PEP 621および `pyproject.toml` を完全にネイティブ理解するため、追加の設定ファイルすら不要な場合が多い。
1. 驚異的な速度での仮想環境作成と依存関係の同期
uv venv –python 3.11
source .venv/bin/activate
2. ロックファイルの生成(uvは高速な依存関係リゾルバを持つ)
uv pip compile pyproject.toml -o requirements.lock
3. ロックファイルからの超高速インストール
uv pip sync requirements.lock
uv pip install -e “.[dev]”
—
4. CI/CDパイプラインとの高度な統合(GitHub Actions 実例)
現場の生産性を極限まで高めるため、GitHub Actionsを用いたCI/CDパイプラインでの `uv` を活用した超高速ビルド・テスト・検証のパイプラインコードを提示する。キャッシュのヒット率を最大化する設計に注目してほしい。
name: Production CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
validate-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: “3.11”
# Astral社公式の uv セットアップアクション(数秒でバイナリが導入される)
- name: Set up uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
version: “latest”
- name: Create virtual environment and install dependencies
run: |
# uvは仮想環境の作成とインストールをワンストップかつ並列で爆速処理する
uv venv .venv
echo “$PWD/.venv/bin” >> $GITHUB_PATH
uv pip install –no-build-isolation -e “.[dev]”
- name: Run Linting (Ruff)
run: |
# 高速リンター Ruff による静的解析
ruff check src/ tests/
- name: Run Type Checking (Mypy)
run: |
# 厳格な型チェック
mypy src/
- name: Run Unit Tests (Pytest)
run: |
# pytestによる単体テスト実行とカバレッジ測定
pytest –cov=enterprise_engine –cov-report=xml
- name: Build Wheel Artifact
if: github.ref == ‘refs/heads/main’ && github.event_name == ‘push’
run: |
# 本番マージ時のみ、wheelパッケージをビルド
uv pip install build
python -m build –wheel
このパイプラインは、従来のpipベースの環境構築と比較して、CIの実行時間を平均で70%以上削減する。キャッシュ機構が `pyproject.toml` のハッシュ値を検知するため、依存関係が変わらない限り一瞬でセットアップが完了する仕組みだ。
—
5. アーキテクトからの提言:移行戦略ロードマップ
レガシーな `setup.py` や `requirements.txt` を抱える既存プロジェクトを、破綻させずにPEP 621へと移行するためのロードマップを授けよう。
1. フェーズ1(メタデータの分離):
まず、`setup.py` の中に散らばっているメタデータ(依存関係、名前、バージョン、ライセンス)を抽出し、`pyproject.toml` の `[project]` セクションへ完全に移植する。
2. フェーズ2(ビルドバックエンドの近代化):
`setup.py` を完全に削除し、`hatchling` や `flit-core` などの標準的なビルドバックエンドへ切り替える。これにより、`pip install -e .` がPEP 660(Editable installs for PEP 621)準拠となり、安全かつ高速になる。
3. フェーズ3(ツールの選択と最適化):
開発者体験(DX)を重視するなら `Poetry`、パイプラインの極限のパフォーマンスと柔軟性を求めるなら `uv` を導入する。どちらを選んでも、核となる `pyproject.toml` 自体は共通の財産として残り続ける。
技術のトレンドに振り回されるな。標準規格(PEP)に準拠し、データとロジックを分離すること。それこそが、何年経っても陳腐化しない、真に強靭なバックエンドアーキテクチャの極意である。