PipとPoetryはもう不要:Pythonツールをuvに一本化すべき理由

Programming tutorial - IT technology blog
Programming tutorial - IT technology blog

Pythonツール疲弊の終焉

Pythonエコシステムに1週間でも触れたことがあれば、依存関係管理特有のフラストレーションを経験したことがあるでしょう。長年、私たちはワークフローを継ぎ接ぎして凌いできました。インストールには pip、隔離には venv、バージョンの切り替えには pyenv、実そして依存関係解決の複雑な処理には Poetrypip-tools を使ってきました。

この断片化は疲弊を招きます。機能的な「Hello World」に到達するためだけに、4つもの異なるツールが必要になるのです。さらに悪いことに、pip は遅いことで有名ですし、Poetryが依存関係をロックするのを待つのは、まるでペンキが乾くのを眺めているような気分になります。ここで uv が状況を一変させます。Ruffの開発元であるAstralチームによって構築された uv は、Pythonスタック全体を置き換えることを目指した、Rust製の単一かつ統合されたツールです。

uvとは一体何か?

根本的に、uv は高性能なPythonパッケージインストーラー兼リゾルバーです。しかし、単なるインストーラーと呼ぶのは、その多才さを見過ごしています。これは以下のような機能を備えたスイスアーミーナイフです:

  • パッケージマネージャー: pippip-compile のドロップイン代替。
  • 環境マネージャー: ミリ秒単位で virtualenv を作成。
  • Pythonバージョンマネージャー: pyenv に代わり、Pythonバージョンをダウンロード・管理。
  • プロジェクトマネージャー: Poetry のようにロックファイルと依存関係を管理。

独立したRustバイナリであるため、uv は動作に既存 of Pythonインストールを必要としません。これにより、ツールを管理するためのツールをインストールするという「卵が先か鶏が先か」の問題が解決されます。生のパフォーマンスに関しては、グローバルキャッシュと積極的な並列化を利用することで、通常 pip よりも10倍から100倍速くパッケージを解決・インストールします。

始め方

uv は数秒でインストールできます。複雑なシェル設定を必要とする他のマネージャーとは異なり、uv はクリーンな7MBのバイナリとして配布されています。

# macOSおよびLinuxの場合
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windowsの場合
powershell -ExecutionPolicy ByPass -c "ir https://astral.sh/uv/install.ps1 | iex"

以下のコマンドを実行して、インストールを確認します:

uv --version

Pythonバージョンをストレスなく管理する

以前は pyenv を使っていましたが、シェルのフックやビルドの依存関係で扱いにくく感じることがよくありました。uv はビルド済みのPythonバイナリを取得することで、これをネイティブに処理します。特定のバージョンを1つのコマンドでインストールできます:

uv python install 3.11 3.12 3.13

このツールはインテリジェントです。プロジェクトにPython 3.12が必要な場合、uv は自動的にそれを見つけるか、ダウンロードします。リポジトリを切り替える際に手動でバージョンを切り替える必要はもうありません。uv.python-versionpyproject.toml を読み取り、面倒な作業を代行してくれます。

効率化されたプロジェクトワークフロー

python -m venv .venv という古い儀式や、常にアクティベーションスクリプトを source する必要性は忘れてください。uv は、私が現在すべての新しいプロジェクトで使用している統合ワークフローを導入しています。

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

mkdir my-new-app
cd my-new-app
uv init

このコマンドは pyproject.toml とサンプルの hello.py を生成します。RustやNode.jsのエコシステムから来た人には馴染み深い感覚でしょう。

2. 依存関係の追加

パッケージの追加はほぼ一瞬です。コーヒーを淹れる暇もなく、uv は依存関係ツリーを解決し、uv.lock ファイルを更新します。

uv add fastapi uvicorn requests

最近のプロジェクトでは、CIパイプラインを pip install から uv sync に切り替えたことで、ビルド時間が4分からわずか28秒に短縮されました。このスピードは単なる贅沢ではありません。コードを反復する頻度を根本的に変えるものです。

3. コードの実行

環境の手動アクティベーションは、今やオプションです。プロジェクトのロックされた環境内で uv run を使用して直接スクリプトを実行できます:

uv run python hello.py
# またはWebサーバーを起動
uv run uvicorn main:app --reload

PEP 723によるポータブルなスクリプト

uv の際立った機能の1つは、PEP 723(インラインスクリプトメタデータ)のサポートです。単一のPythonファイルを記述し、その依存関係をコメント内に直接定義できます。これは、別の requirements.txt を送ることなくユーティリティスクリプトを共有するのに最適です。

# script.py
# /// script
# dependencies = ["requests", "rich"]
# ///

import requests
from rich import print

response = requests.get("https://api.github.com/zen")
print(f"[bold green]GitHubは言っています:[/bold green] {response.text}")

uv run script.py で実行します。uv は一時的な隠し環境を作成し、2つのパッケージをインストールし、コードを実行して、後片付けをします。これにより、グローバル環境をクリーンに保つことができます。

Dockerビルドの最適化

PythonアプリのDocker化は、肥大化したレイヤーと遅い pip install を伴うものでした。uv は、キャッシュをマウントしたり、--frozen フラグを使用して本番環境を開発時のロックファイルと完全に一致させたりすることで、これを効率化します。

FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen

COPY . .
CMD ["uv", "run", "python", "main.py"]

このセットアップにより、レガシーツールのオーバーヘッドなしに、ビット単位の再現性が保証されます。

なぜ移行が避けられないのか

Pythonコミュニティは猛烈な勢いで uv へと移行しています。それは単に10倍のスピードアップのためだけではありません。ワークフローのどの部分をどのツールが管理しているかを覚えておくという、精神的なコストを削減するためでもあります。すべてを1つのバイナリに集約することで、セットアップは予測可能になり、信じられないほど高速になります。

私は自分のマシンから pyenvvirtualenv を完全に削除しました。uvpyproject.toml 標準を尊重しているため、移行は事実上痛みなしで行えます。たとえ今 Poetry を使っていたとしても、uv は設定を1行も変更することなく、それらのプロジェクトを管理できます。

最後に

環境管理は、かつてPython開発で最も退屈な部分でした。uv はそのフラストレーションを、ほとんど意識する必要のないバックグラウンドタスクに変えてくれます。これは、Pythonが10年前から切実に必要としていた「Cargo」のような存在です。自分の時間を大切にするなら、次のプロジェクトで uv を試してみてください。もう元には戻りたくなくなるはずです。

Share: