こんにちは、データ分析おじさんです。
今日は最近話題の Python 環境管理ツール uv を触ってみた話を書きます。
「pip と venv を毎回作って管理するのめんどくさいなあ」と思っている方にぜひ読んでもらいたい内容です。さらにおまけとして躓きがちな「PyTorch の GPU 版を uv で入れる方法」も最後に書いておきます。
uvとは何か?
uvは、Rust製の高速なPythonパッケージ・プロジェクト管理ツールです。従来のpip・venv・pyenvなど複数のツールの機能を1つにまとめて提供しており、以下の特徴があります。
- 圧倒的な速さ: 標準の
pipよりも10~100倍高速に動作するとされています。 - オールインワン: uvだけでPythonのバージョン管理、仮想環境の作成、パッケージのインストール/更新、ロックファイル生成など一通りを完結できます。
- グローバルキャッシュ: 依存パッケージを共有キャッシュに保存し、二回目以降のインストールを高速化します。
- クロスプラットフォーム対応: macOS、Linux、Windowsに対応しており、単一のバイナリで動作します。
- 幅広い機能:
pip,pip-tools,pipx,poetry,pyenvなど多くのツールの機能を置き換えることが可能で、仮想環境や依存関係の管理、Pythonインストールの管理、パッケージの公開なども行えます。Astral(高速リンターRuffの開発元)が支援しているプロジェクトであり、新世代のPython開発環境構築ツールとして注目されています。
uvのインストール (Windowsの場合)
uvはスタンドアロンのインストーラや各種パッケージマネージャー経由でインストールできます。Windows環境では、公式が提供するPowerShellスクリプトを使う方法が手軽です。以下のコマンドをPowerShellで実行すると、最新版のuvをダウンロードしてインストールしてくれます。
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"スクリプトの実行後、uv本体 (実行ファイル) は通常ユーザーディレクトリ配下の.local\bin\uvにインストールされます。環境変数PATHにそのパスが含まれていない場合は、以下のように追加してください:
$env:Path = "C:\Users\<ユーザー名>\.local\bin;$env:Path"最後に、コマンドプロンプトやPowerShellでuv --versionを実行し、バージョン情報が表示されればインストール成功です。
その他のインストール方法: 上記以外にも、WindowsならWinGet経由でwinget install astral-sh.uvとインストールしたり、Python環境がある場合はpipx install uv(推奨)やpip install uvで導入することも可能です。HomebrewやScoop、Dockerイメージ、Cargo経由のビルドなど多彩な方法が用意されています。自分の環境に合った方法で導入してください。
プロジェクトの初期化とPythonバージョン指定
uvを使ったプロジェクトの作成はシンプルです。まず、作業したいフォルダに移動して以下を実行します。
uv initこれで現在のディレクトリにプロジェクトが初期化され、pyproject.tomlという設定ファイルが生成されます。さらに、基本的な雛形としてmain.py(サンプルスクリプト)やREADME.md、Pythonのバージョン指定ファイルである.python-versionが自動作成されます。
uv init example例えば「example」という名前でプロジェクトを初期化すると以下のような構成のフォルダが作成されます。
example/
├── .python-version ← プロジェクトで使用するPythonのバージョン指定
├── README.md ← 説明書き用のREADME
├── main.py ← サンプルのPythonスクリプト
└── pyproject.toml ← プロジェクト設定と依存パッケージ一覧
生成されたpyproject.tomlにはプロジェクト名やバージョン、説明、READMEファイル、サポートするPythonバージョンなどの基本情報が記載されています(初期状態では依存パッケージリストは空の状態です)。
Pythonバージョンの管理
uvはPython自体のインストール管理機能も備えており、プロジェクトごとに使用するPythonのバージョンを指定・切り替えすることができます。既にシステムにPythonがインストール済みなら特別な設定は不要で、そのバージョンを自動検出して利用します。もしインストールされていなければ、uv経由で以下のようにインストール可能です。
uv python install 3.12上記はPython 3.12をダウンロードしてインストールする例です。また、uv python listとすれば、システムおよびuvで管理可能なPythonバージョンの一覧を表示できます。
プロジェクトで使用するPythonのバージョンを固定したい場合は、例えば次のようにuvにバージョンをピン留めできます。
uv python pin 3.12このコマンドを実行するとプロジェクトルートに.python-versionファイルが作成(または更新)され、以後そのプロジェクトでは指定バージョンのPythonが使われます。uv init --python 3.12のように初期化時にオプション指定しておけば、最初から特定バージョンのPythonを使うプロジェクトを作成することもできます。
仮想環境の作成とパッケージ管理
uvでは各プロジェクトごとに独立したPython仮想環境を作成し、その中にパッケージをインストールします。これによりプロジェクト間でインストールしたライブラリが干渉せず、依存関係を分離できます。uv自体がvenvコマンドをラップしているため、手動で仮想環境を作成する場合は以下のように実行可能です。
uv venv # カレントディレクトリに .venv 仮想環境を作成上記を実行すると、プロジェクト直下にデフォルト名の仮想環境フォルダ「.venv」が作成されます。特定のフォルダ名を指定したい場合はuv venv myenvのように名前を引数で渡すこともできます。また、uv venv --python 3.11とすると、そのPython 3.11環境で仮想環境を構築することも可能です(未インストールならuvが自動で該当Pythonをダウンロードします)。
※Tips: 一般的にuvでは常に仮想環境を使用することが推奨されます。pipコマンドとは異なり、uvはデフォルトでグローバル環境へのパッケージインストールを行わず、必ず何らかの仮想環境上にパッケージを導入する設計になっています。そのため、もし仮想環境が存在しない状態で依存関係を追加しようとすると、自動的に環境を作るかエラーを出す挙動になります。
実際、プロジェクト作成直後はまだ仮想環境がありませんが、uvでパッケージを追加するタイミングで仮想環境が自動生成されます例えば以下のように、ruffというパッケージを追加してみます。
$ uv init example # プロジェクト作成
Initialized project `example` at `.../example`
$ cd example
$ uv add ruff # パッケージ追加(この時点で.venvが作成される)
Creating virtual environment at: .venv
Resolved 2 packages in 170ms
...
Installed 2 packages in 1ms
+ example==0.1.0
+ ruff==0.5.4:contentReference[oaicite:35]{index=35}
上記のようにuv addコマンドで依存パッケージを追加すると、最初の一回は自動で.venvフォルダが作られ、その中にパッケージがインストールされます。.venvが既に存在する場合はその環境が使われます。uvは以降のコマンド実行時にカレントディレクトリ内の.venvを自動検出して使用するため、特別な操作をしなくても仮想環境下でコマンドを実行できます。
パッケージの追加・管理
パッケージの追加は先述のようにuv add パッケージ名で行います。
$ uv add ruff # ruffパッケージ追加(この時点で.venvが作成される)uv addを実行すると、そのパッケージと依存関係が解決され、.venvにインストールされると同時に、pyproject.tomlの[project] dependenciesセクションに追記されます。たとえばuv add requestsとすればrequestsライブラリが導入され、pyproject.tomlのdependenciesに"requests>=2.x"という形で記録されます(バージョン指定なしの場合、自動的に最新バージョンに適合するようエントリが追加されます)。
バージョンや条件の指定: 特定のバージョンや条件付きでパッケージを追加したい場合、従来のpipと同様の書式が利用できます。例えばuv add "Django==4.2.5"とすればそのバージョンに固定され、uv add "jax; sys_platform == 'linux'"のように書けば特定のOSでのみ有効な依存関係を追加することもできます。uvはpip互換のインターフェースを持つため、このような環境マーカー付きの指定にも対応しています。
開発(dev)依存: 開発時だけ必要なパッケージ(テストフレームワークやリンターなど)を分離したい場合、uvではDependency Groupsの仕組みで管理します。uv add --dev パッケージ名とすることで、そのパッケージは開発用グループdevに追加され、pyproject.toml内では[dependency-groups]セクションに記録されます。デフォルトではdevグループは通常の依存と同様にインストール対象となりますが、後述するuv syncのオプションで含める/除外を制御することも可能です。
ロックファイルによる環境の再現と同期
プロジェクトで必要なパッケージをすべてuvで追加し終えたら、ロックファイルを生成して依存関係のバージョンを固定することができます。uvでは解決した依存パッケージのバージョンを記録したロックファイルuv.lockを使用します。このファイルには直接インストールしたパッケージだけでなく、その依存関係(間接依存)も含め、環境を再現するために必要なすべての正確なバージョン情報がTOML形式で保存されます。
ロックファイルの生成は簡単で、以下のコマンドを実行するだけです:
uv lock上記を実行すると、現在のpyproject.tomlに基づいて最新版が解決されたロックファイルuv.lockが作成(または更新)されます。uvはプロジェクトのメタデータとロックファイルの差分を常に監視しており、もしpyproject.tomlに新たな依存を追加したりバージョン変更すれば、その時点でロックファイルは古い状態とみなされます。そのため、新たな変更後には改めてuv lockを実行して最新の組み合わせを固定する運用になります。
ロックファイルをプロジェクトリポジトリに含めて共有することで、他の開発者や他環境で同一の環境を再現できます。受け手側では、プロジェクトをクローン後に以下を実行すればOKです。
uv syncuv syncコマンドはロックファイルに記録された通りに仮想環境を同期(インストール)します。具体的には、pyproject.tomlとuv.lockを照らし合わせ、必要なパッケージがすべて正しいバージョンで.venvにインストールされているか確認します。不足があればインストールし、余計なものが入っていれば削除します(uvの同期はデフォルトで「正確(exact)」に行われ、ロックファイルにないパッケージは削除されます)。これにより、チーム全員やCI環境で同一のセットアップを簡単に構築できるわけです。
ロックファイルと同期のポイント:
- 自動同期: 実はuvは多くの場合明示的に
uv syncしなくても、コマンド実行時に自動で環境を最新状態に保つようになっています。例えばuv runやuv test実行時に必要なら自動同期が走ります。ただ、エディタに補完情報を認識させる目的や、手動で確認したい場合にuv syncを使うとよいでしょう。 - ロックファイルの更新: 既存ロックファイルがある状態で新しいバージョンにアップグレードしたい場合、
uv lock --upgradeオプションが利用できます。特定パッケージのみ最新化する--upgrade-packageオプションもあります。アップグレード後は必要に応じてチームに新しいuv.lockを共有します。 - フォーマット変換: 他ツールとの連携が必要な場合、
uv lockの内容をrequirements.txt形式にエクスポートする機能もあります(uv export --format requirements-txt)。基本的にはuv.lock一本で管理するのが望ましいですが、状況に応じて利用できます。
PyTorch GPU版のインストール (応用)
機械学習で人気のPyTorchをuv経由で導入する際、GPU対応版を入れたい場合には注意が必要です。PyTorchのパッケージ(例: torch, torchvision)は特殊で、多くの公式ホイールがPyPIではなく専用のインデックス(ホスト)に置かれているという点があります。特にCUDA対応のGPU版PyTorchは、バージョン番号に+cu117や+cu121といったタグが付与された別ビルドが存在し、それぞれ公式サイトの専用URLから提供されています。例えばWindowsやLinux向けのCUDA 11.8ビルドはhttps://download.pytorch.org/whl/cu118というインデックスにあり、CPU版は/cpuというインデックスに置かれています。
そのため、uvでGPU版をインストールするにはPyPI以外のインデックスをプロジェクトに追加設定し、該当パッケージにそのインデックスを使うよう指定する必要があります。具体的には、プロジェクトのpyproject.tomlに以下のような追記を行います。
[[tool.uv.index]]
name = "pytorch-cu118"
url = "https://download.pytorch.org/whl/cu118"
explicit = true
PyTorch公式インデックスの登録:
まず[[tool.uv.index]]セクションでPyTorch用インデックスを追加します。例えばCUDA 11.8対応のホイールを利用したい場合は任意の識別子、urlはインデックスのURLです。explicit = trueとすることで、このインデックスは指定したパッケージに対して明示的に使用する場合のみ参照され、他の一般パッケージ(例えばnumpyやjinja2など)には誤って使われないようにできます。
特定パッケージにインデックスを適用:
次に[tool.uv.sources]セクションで、PyTorch関連パッケージに先ほど定義したインデックスを利用するようマップします。例えばWindowsとLinuxではCUDA版を使い、その他のプラットフォームではデフォルトのPyPIを使う設定をするには、環境マーカーsys_platformを用いて以下のように記述します。
[tool.uv.sources]
torch = [
{ index = "pytorch-cu118", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
torchvision = [
{ index = "pytorch-cu118", marker = "sys_platform == 'linux' or sys_platform == 'win32'" },
]
以上の設定をpyproject.tomlに追加し、uvで依存関係としてtorchやtorchvisionを指定すれば、GPU版PyTorch環境を構築できます。例えば、上記設定でuv add torch torchvisionとすると、適切なインデックスから対応するビルドが取得されるようになります。このようにuvではプロジェクト設定ファイル経由でパッケージごとにインストール元を柔軟に切り替えられるため、追加のコマンドオプション無しに環境構築の再現性を高めることができます。
おわりに
本記事では、新しいPython開発環境ツールuvの基本的な使い方について、Windows環境を例にインストールからプロジェクト初期化、仮想環境の管理、パッケージ追加、ロックファイルを用いた環境再現、そして応用として躓きがちなPyTorch GPU版の導入方法までをまとめました。uvを用いることで各プロジェクトごとに.venvディレクトリが作成され、その中で依存パッケージが管理されるため、複数プロジェクトの環境が混ざる心配がありません。またpyenvやvenv、pip、poetryといった複数ツールを組み合わせて行っていた作業をuv一つで完結でき、しかも非常に高速に動作します。
まだバージョン0.x台の若いツールではありますが、公式ドキュメントやコミュニティも充実しており、2025年現在において有力なパッケージ管理ソリューションの一つと言えます。従来のツールに不便さを感じている方は、この機会にuvを試してみてはいかがでしょうか。各プロジェクトで快適かつ再現性の高いPython開発環境を構築できるはずです。



コメント