1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

uv とは何か?その設計思想と再現性ある環境構築のためのガイド

1
Posted at

はじめに

Pythonのパッケージ管理ツール「uv」を使っている人は増えてきたが、「速いpip」程度の認識で使っていないだろうか?

実は uv には明確な設計思想があり、それを理解せずに使うと本来の力を発揮できない。本記事では uv の設計思想を解説し、再現性のある環境構築のためのベストプラクティスを紹介する。

uv とは

uv は Astral 社が開発した、Rust製のPythonパッケージ・プロジェクト管理ツールだ。

従来のPython開発では複数のツールを組み合わせる必要があった:

  • pyenv: Pythonバージョン管理
  • venv / virtualenv: 仮想環境作成
  • pip: パッケージインストール
  • pip-tools: 依存関係のロック
  • build / twine: パッケージのビルド・公開

uv はこれらを単一のツールで置き換えることを目指している。しかも10〜100倍速い。

uv の設計思想: pyproject.toml を Single Source of Truth に

uv の最も重要な設計思想は、pyproject.toml をプロジェクトの唯一の真実の情報源(Single Source of Truth)にすることだ。

従来の問題点

従来のpipベースのワークフローでは、依存関係の情報が散らばりがちだった:

requirements.txt        # 本番依存
requirements-dev.txt    # 開発依存
requirements-test.txt   # テスト依存
setup.py               # パッケージメタデータ
setup.cfg              # 追加設定

どれが正なのか? 更新漏れは? 同期は取れている? こうした問題が常につきまとう。

uv のアプローチ

uv では pyproject.toml に全ての情報を集約する:

[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
    "httpx>=0.27.2",
    "pydantic>=2.0.0",
]

[project.optional-dependencies]
excel = ["openpyxl>=3.1.0"]

[dependency-groups]
dev = ["pytest>=8.0.0", "ruff>=0.4.0"]
test = ["pytest-cov>=5.0.0"]

[tool.uv.sources]
# 開発時のみ使う特殊なソース指定

この1ファイルを見れば、プロジェクトの全ての依存関係がわかる。

uv pip install vs uv add: 2つのインターフェースの違い

ここが最も誤解されやすいポイントだ。

uv には2つの異なるインターフェースがある:

1. uv pip 系コマンド(pip互換レイヤー)

uv pip install httpx
uv pip install -r requirements.txt
uv pip freeze

これらは pip からの移行を容易にするための互換レイヤー として提供されている。

特徴:

  • venv環境に直接パッケージをインストール
  • pyproject.toml変更しない
  • uv.lock更新しない
  • 一時的なテストや、pipとの互換性が必要な場面向け

2. uv add / uv sync 系コマンド(uvネイティブ)

uv add httpx
uv add -r requirements.txt  # requirements.txtからインポート
uv sync
uv lock

これが uv 本来の使い方 だ。

特徴:

  • pyproject.toml[project.dependencies] を更新
  • uv.lock を自動生成・更新
  • tool.uv.sources にソース情報を記録
  • 再現性のある環境構築が可能

比較表

コマンド pyproject.toml uv.lock 主な用途
uv add <package> 更新 更新 正式な依存追加
uv remove <package> 更新 更新 依存の削除
uv sync 読み取り 適用 lockfileから環境を同期
uv lock 読み取り 更新 lockfileの再生成
uv pip install 変更なし 変更なし 一時的なテスト

なぜ uv pip install requirements.txt が推奨されないのか

# これをやると...
uv pip install -r requirements.txt

# pyproject.toml には何も残らない
# チームメンバーが uv sync しても何もインストールされない
# 再現性ゼロ

正しいアプローチ:

# requirements.txt の内容を pyproject.toml にインポート
uv add -r requirements.txt

再現性ある環境構築のベストプラクティス

1. プロジェクトの初期化

# 新規プロジェクト
uv init my-project
cd my-project

# 既存プロジェクトに uv を導入
uv init --bare

2. 依存関係の追加

# 本番依存
uv add httpx pydantic

# 開発依存
uv add --dev pytest ruff mypy

# 特定のグループに追加
uv add --group test pytest-cov

# オプショナル依存(extras)
uv add --optional excel openpyxl

3. 環境の同期

# uv.lock に基づいて環境を同期(推奨)
uv sync

# 開発依存を含めて同期
uv sync --all-groups

# 特定のグループのみ
uv sync --group test

4. uv.lock のバージョン管理

uv.lock は必ず Git にコミットする。 これが再現性の鍵だ。

# .gitignore
.venv/
__pycache__/
# uv.lock は含めない!コミットする!

uv.lock があれば、どの環境でも同じバージョンの依存関係がインストールされる。

5. CI/CD での利用

# GitHub Actions の例
- name: Install uv
  uses: astral-sh/setup-uv@v4

- name: Install dependencies
  run: uv sync --frozen  # lockfile を変更しない

- name: Run tests
  run: uv run pytest

--frozen フラグにより、CI環境でlockfileが意図せず更新されることを防ぐ。

依存ソースの指定(tool.uv.sources)

uv の強力な機能の1つが tool.uv.sources だ。開発時のみ使う特殊なソースを指定できる。

Git リポジトリから

[project]
dependencies = ["httpx"]

[tool.uv.sources]
httpx = { git = "https://github.com/encode/httpx", tag = "0.27.0" }

ローカルパスから

[project]
dependencies = ["my-lib"]

[tool.uv.sources]
my-lib = { path = "../my-lib", editable = true }

特定のインデックスから

[project]
dependencies = ["torch"]

[tool.uv.sources]
torch = { index = "pytorch" }

[[tool.uv.index]]
name = "pytorch"
url = "https://download.pytorch.org/whl/cpu"

重要: tool.uv.sources は開発時のみ使用される。パッケージを公開する際は --no-sources でビルドすることが推奨される。

uv build --no-sources

よくある間違いと対処法

間違い1: uv pip install をメインで使う

# NG: pyproject.toml に反映されない
uv pip install pandas numpy

# OK: 依存関係として記録される
uv add pandas numpy

間違い2: uv.lock を .gitignore に入れる

# NG: 再現性が失われる
uv.lock

# OK: uv.lock はコミットする
# (.gitignore に含めない)

間違い3: uv sync せずに uv run する

# 実は uv run は自動で sync してくれる
uv run pytest  # OK: 内部で sync が走る

# 明示的に sync したい場合
uv sync && uv run pytest

uv run は実行前に自動で環境を同期するので、常に pyproject.tomluv.lock に基づいた正しい環境でコマンドが実行される。

間違い4: 仮想環境を手動で activate する

# 従来のやり方(uvでは不要)
source .venv/bin/activate
python script.py

# uv のやり方
uv run python script.py
uv run pytest

uv run を使えば、仮想環境の activate は不要。

まとめ

uv を「速いpip」として使うのはもったいない。その設計思想を理解して使おう:

  1. pyproject.toml を Single Source of Truth に: 全ての依存情報を1箇所に集約
  2. uv add を使う: uv pip install ではなく uv add で依存を追加
  3. uv.lock をコミット: 再現性のある環境構築の鍵
  4. uv sync / uv run を活用: 常に正しい環境で作業

これらを実践すれば、「自分の環境では動くのに...」という悲劇とはおさらばできる。

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?