uv (pythonパッケージマネージャー)の使い方 詳細版
Pythonのパッケージ管理はこれまで pip
、venv
、poetry
などで行われてきましたが、最近 uv
が注目を集めています。
本稿では uv
をシステム開発で使うための詳細な情報、特に、poetry
、venv
、pip
からの移行手順を解説します。
1. uvの概要
1.1 uvとは?
uvは 高速な動作、クロスプラットフォーム対応のロックファイル、ツール管理の専用インターフェースを提供することで、快適な開発環境を実現しています。
1.2 uvのアーキテクチャ
uvはRustで実装されており、高いパフォーマンスとメモリ安全性を誇ります。Rustの並行処理能力を活用し、依存関係解決を高速化しています。また、効率的なキャッシュ機構を備えており、ダウンロードしたパッケージ、ビルドされたwheelファイル、ソースコードなどをキャッシュすることで、再利用性を高め、処理時間を短縮します。このキャッシュはスレッドセーフであり、複数のコマンドを同時実行しても安全に動作します。
1.3 uvのインストールとセットアップ
uvのインストールは、公式のスタンドアロンインストーラーを利用するのが最も簡単です。macOSとLinuxではcurlコマンド、WindowsではPowerShellコマンドを実行することで、最新版のuvをダウンロードしてインストールできます。
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
また、pip、Homebrew、Cargoといったパッケージマネージャーからもインストール可能です。
# pip
pip install uv
# Homebrew
brew install uv
# Cargo
cargo install --git https://github.com/astral-sh/uv uv
インストール後、uv generate-shell-completion
コマンドを実行することで、シェルに自動補完機能を追加できます。
uvのアップグレードは、uv self update
コマンドで実行できます。アンインストールは、インストールディレクトリからuvのバイナリを削除するだけで完了します。
2. uvの基本的な使い方
2.1 Pythonバージョンの管理
uvは、複数のPythonバージョンを管理することができます。uv python install
コマンドで、任意のバージョンのPythonをインストールできます。
uv python install 3.10 3.11 3.12
uv python list
コマンドで、インストール済みのPythonバージョンを確認できます。
uv python list
プロジェクトごとに使用するPythonバージョンを指定するには、.python-version
ファイルにバージョンを記述します。
uvは、必要に応じてPythonバージョンを自動的にダウンロードします。自動ダウンロードを無効にするには、--no-python-downloads
オプションを使用します。
2.2 スクリプトの実行
uvは、スタンドアロンスクリプトの実行をサポートしています。uv run
コマンドで、スクリプトを実行できます。
uv run example.py
スクリプトに必要な依存関係は、--with
オプションで指定します。
uv run --with requests example.py
また、スクリプトの先頭にインラインメタデータを記述することで、依存関係を宣言できます。
# /// script
# dependencies = ["requests"]
# ///
import requests
# ...
再現性を向上させるために、tool.uv.exclude-newer
フィールドを使用して、特定の日付より前にリリースされたパッケージのみを使用するように制限することもできます。
2.3 ツールの実行とインストール
uvは、Pythonパッケージが提供するコマンドラインツールの実行とインストールをサポートしています。uvx
コマンド (またはuv tool run
) で、ツールを実行できます。
uvx ruff
ツールは、一時的な隔離環境にインストールされます。永続的な環境にツールをインストールするには、uv tool install
コマンドを使用します。
uv tool install ruff
パッケージ名とコマンド名が異なる場合は、--from
オプションを使用します。
uvx --from httpie http
特定のバージョンのツールを実行するには、@
記法を使用します。
uvx ruff@0.3.0 check
ツールにプラグインが必要な場合は、--with
オプションで追加の依存関係を指定します。
uvx --with mkdocs-material mkdocs --help
3. uvによるプロジェクト管理
3.1 プロジェクトの作成と初期化
uvは、pyproject.toml
ファイルで定義されたPythonプロジェクトの管理をサポートしています。uv init
コマンドで、新しいプロジェクトを作成できます。
uv init my-project
--app
オプションでアプリケーションプロジェクト、--lib
オプションでライブラリプロジェクトを作成できます。
# アプリケーションプロジェクト
uv init --app my-app
# ライブラリプロジェクト
uv init --lib my-lib
さらに、--package
オプションを指定することで、配布可能なアプリケーションを作成できます。これは、PyPIなどを介してコマンドラインインターフェースを公開する場合に便利です。
uv init --app --package my-cli
uv init
では、hatchling
、flit-core
、pdm-backend
、setuptools
、maturin
、scikit-build-core
といったビルドバックエンドを選択できます。--build-backend
オプションで、使用するバックエンドを指定します。
uv init --lib --build-backend maturin my-lib
3.2 依存関係の管理
uv add
コマンドで、pyproject.toml
に依存関係を追加できます。
uv add requests
--editable
オプションで、編集可能な依存関係を追加できます。
uv add --editable ./path/to/my-package
--dev
オプションで、開発用の依存関係を追加できます。
uv add --dev pytest
--optional
オプションで、オプションの依存関係を追加できます。
uv add --optional pandas pandas[excel]
uv remove
コマンドで、依存関係を削除できます。
uv remove requests
uv add
コマンドで、既存の依存関係を更新することもできます。
uv add 'requests>2.30.0'
3.3 環境の管理
uvは、プロジェクトごとに仮想環境を自動的に作成します。uv sync
コマンドで、環境を最新の状態に同期できます。
uv sync
--no-editable
オプションで、プロジェクトを編集不可モードでインストールできます。これは、Dockerコンテナの構築など、デプロイ時に便利です。
UV_PROJECT_ENVIRONMENT
環境変数で、プロジェクトの仮想環境のパスを設定できます。
3.4 ロックファイルの管理
uvは、uv.lock
というクロスプラットフォームのロックファイルを生成します。uv lock
コマンドで、ロックファイルを明示的に更新できます。
uv lock
--upgrade
オプションで、すべてのパッケージを最新バージョンにアップグレードできます。
uv lock --upgrade
--upgrade-package
オプションで、特定のパッケージをアップグレードできます。
uv lock --upgrade-package requests
tool.uv.environments
設定で、解決するプラットフォームを制限できます。
3.5 ワークスペースの活用
uvは、Cargoスタイルのワークスペースをサポートしています。ワークスペースは、複数のパッケージをまとめて管理するための機能です。
pyproject.toml
にtool.uv.workspace
テーブルを追加することで、ワークスペースを作成できます。
[tool.uv.workspace]
members = ["packages/*"]
members
キーで、ワークスペースメンバーを指定します。exclude
キーで、除外するディレクトリを指定できます。
ワークスペースメンバーは、tool.uv.sources
で依存関係として宣言します。
[tool.uv.sources]
my-package = { workspace = true }
ワークスペースルートのtool.uv.sources
は、すべてのメンバーに適用されます。
4. uvの高度な機能
4.1 依存関係の解決
uvは高度な依存関係解決アルゴリズムを備えています。uvの依存関係解決は、以下の要素を考慮します。
- バージョン制約: 各パッケージに指定されたバージョン範囲
- プラットフォームマーカー: OS、アーキテクチャ、Pythonバージョンなどの条件
- 依存関係の競合: 異なるパッケージが同じ依存関係の異なるバージョンを要求する場合
uvは、これらの要素を考慮しながら、すべての依存関係を満たす最適なパッケージの組み合わせを探索します。このプロセスがめっちゃ高速に行われます。
uvは、ユニバーサル解決とプラットフォーム固有の解決の両方をサポートしています。ユニバーサル解決では、すべてのプラットフォームで動作するロックファイルを生成します。これは、チーム開発やCI/CD環境で特に役立ちます。プラットフォーム固有の解決では、特定のプラットフォームに最適化されたロックファイルを生成します。
uvは、依存関係の解決時に、最新バージョンを優先します。これは、常に最新のパッケージを使用することで、セキュリティリスクを軽減し、新機能を活用できるという利点があります。ただし、必要に応じて、--resolution lowest
オプションで最低バージョンを優先したり、--resolution lowest-direct
オプションで直接依存関係のみ最低バージョンを優先したりすることもできます。
4.2 キャッシュの管理
uvは、強力なキャッシュ機構を備えています。ダウンロードしたパッケージ、ビルドされたwheelファイル、ソースコードなどをキャッシュすることで、依存関係の解決とインストールを高速化します。
uvのキャッシュは、以下の特徴があります。
- 効率性: 依存関係の再利用性を高め、処理時間を短縮
- 安全性: スレッドセーフであり、複数のコマンドを同時実行しても安全
- 柔軟性: キャッシュディレクトリの設定、キャッシュのクリア、プルーニングなど、柔軟な管理が可能
uv cache clean
コマンドで、キャッシュをすべて削除できます。uv cache prune
コマンドで、未使用のキャッシュエントリを削除できます。--cache-dir
オプションで、キャッシュディレクトリを指定できます。
4.3 ビルドの分離
uvは、PEP 517とPEP 660に準拠したビルドの分離をサポートしています。これは、各パッケージを隔離された環境でビルドすることで、依存関係の競合を防ぎ、ビルドの再現性を向上させるための機能です。
ただし、一部のパッケージはビルドの分離に対応していません。そのようなパッケージをインストールする場合は、no-build-isolation-package
設定でビルドの分離を無効にする必要があります。
[tool.uv]
no-build-isolation-package = ["my-package"]
ビルドの分離を無効にする場合は、パッケージのビルドに必要な依存関係を事前にインストールしておく必要があります。
4.4 パブリッシュ
uvは、uv build
コマンドでPythonパッケージをソースディストリビューションとバイナリディストリビューションにビルドし、uv publish
コマンドでレジストリにアップロードすることができます。
uv publish
コマンドでは、--token
オプションでPyPIトークンを指定するか、--username
オプションと--password
オプションでユーザー名とパスワードを指定することで、認証を行うことができます。
5. uvと他ツールとの連携
uvは、他の開発ツールと連携することで、より強力な開発ワークフローを構築することができます。ここでは、代表的なツールとの連携方法を紹介します。
5.1 Dockerとの連携
uvは、Dockerとの連携に優れており、コンテナ化されたアプリケーションの開発を効率化します。
uvの公式Dockerイメージを利用することで、簡単にuvを実行することができます。また、COPY --from
構文を利用して、uvバイナリを自身のDockerイメージにコピーすることもできます。
FROM python:3.12-slim
COPY /uv /bin/uvx /bin/
プロジェクトをDockerイメージにインストールするには、uv sync
コマンドを使用します。
COPY . /app
WORKDIR /app
RUN uv sync --frozen
.dockerignore
ファイルに.venv
を追加して、プロジェクトの仮想環境がイメージに含まれないようにすることが重要です。
Docker Composeを使用する場合は、watch
オプションで開発環境を構築できます。これにより、プロジェクトの変更がコンテナに即座に反映されます。
services:
example:
build: .
develop:
watch:
- action: sync
path: .
target: /app
ignore:
- .venv/
5.2 GitHub Actionsとの連携
GitHub Actionsでuvを使用するには、公式のastral-sh/setup-uv
アクションを利用するのが便利です。
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
setup-uv
アクションは、uvのインストール、キャッシュの永続化、Pythonのセットアップなどを自動的に行います。
uvとactions/setup-python
アクションを組み合わせて、Pythonのバージョンを指定することもできます。
steps:
- uses: actions/setup-python@v5
with:
python-version-file: ".python-version"
uv sync
コマンドでプロジェクトをインストールし、uv run
コマンドでテストを実行できます。
steps:
- run: uv sync --all-extras --dev
- run: uv run pytest tests
actions/cache
アクションを利用して、uvのキャッシュを永続化することで、ワークフローの実行時間を短縮できます。
5.3 GitLab CI/CDとの連携
GitLab CI/CDでも、uvの公式Dockerイメージを利用できます。
variables:
UV_VERSION: 0.4
PYTHON_VERSION: 3.12
BASE_LAYER: bookworm-slim
uv:
image: ghcr.io/astral-sh/uv:$UV_VERSION-python$PYTHON_VERSION-$BASE_LAYER
script:
# your `uv` commands
GitLab CI/CDのキャッシュ機能を利用して、uvのキャッシュを永続化することもできます。
cache:
- key: uv-cache
paths:
- .uv-cache
5.4 Jupyterとの連携
uvは、Jupyter Notebookとの連携もサポートしています。
プロジェクト内でJupyterを使用するには、uv run
コマンドでJupyterサーバーを起動します。
uv run --with jupyter jupyter lab
ノートブックからパッケージをインストールする場合は、ipykernel
を開発用依存関係として追加し、カーネルを作成します。
uv add --dev ipykernel
uv run ipython kernel install --user --name=my-project
カーネルを作成せずに、プロジェクトの仮想環境にパッケージをインストールする場合は、!uv pip install
コマンドを使用します。
5.5 pre-commitとの連携
uvは、pre-commitとの連携もサポートしています。公式のastral-sh/uv-pre-commit
フックを使用することで、コミット前に uv export --format requirements-txt
を実行し、requirements.txt
を自動生成できます。
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.4.26
hooks:
- id: pip-compile
args: [requirements.in, -o, requirements.txt]
6. poetry, venv, pipからの移行
現在poetry, venv, pipを使用しているチームが、すべてuvに移行する場合、以下の手順がよさそうです。
6.1 poetryからの移行
-
pyproject.tomlの変換: poetryの
pyproject.toml
をuvのpyproject.toml
に変換します。poetryのtool.poetry
セクションをtool.uv
セクションに置き換え、必要な設定を移行します。依存関係は、tool.poetry.dependencies
からproject.dependencies
に移動します。 -
依存関係の移行: poetryの仮想環境にインストールされている依存関係を、uvの仮想環境に移行します。
poetry export -f requirements.txt --output requirements.txt
コマンドで、poetryの依存関係をrequirements.txt
ファイルにエクスポートします。そして、uv pip install -r requirements.txt
コマンドで、uvの仮想環境に依存関係をインストールします。 - 環境の移行: poetryの仮想環境で使用していた設定を、uvの仮想環境に移行します。環境変数、Pythonバージョンなどを確認し、必要に応じてuvの環境に設定します。
6.2 venv, pipからの移行
-
仮想環境の移行: venvで作成した仮想環境を、uvの仮想環境に移行します。
pip freeze > requirements.txt
コマンドで、venvの仮想環境にインストールされている依存関係をrequirements.txt
ファイルにエクスポートします。そして、uv venv
コマンドで新しい仮想環境を作成し、uv pip install -r requirements.txt
コマンドで依存関係をインストールします。 -
依存関係の移行: pipで管理していた依存関係を、uvの
pyproject.toml
に移行します。requirements.txt
ファイルの内容を参考に、project.dependencies
に依存関係を記述します。 -
ワークフローの移行: pipコマンドを
uv pip
コマンドに置き換え、uvのワークフローに適応させます。例えば、pip install
はuv pip install
に、pip freeze
はuv pip freeze
に置き換えます。
7. uvのメリットとデメリット
メリット:
- 高速なパフォーマンス: Rustによる実装により依存関係の解決が超速です。
- クロスプラットフォーム対応: ユニバーサルロックファイルにより、異なるプラットフォーム間での一貫性を確保します。
- 豊富な機能: 依存関係管理、環境管理、ツール管理、スクリプト実行など、Python開発に必要な機能を網羅しています。
- 使いやすさ: シンプルなコマンド体系と分かりやすいドキュメント。
デメリット:
- エコシステムの成熟度: pipに比べて、エコシステムはまだ成熟していないとのことですが、具体的に不都合があるかどうかはまだ体感できていません。
- 学習コスト: 新しいツールであるため、学習コストが必要です。
Discussion