なぜuv run pythonと打つのか – Pythonの仮想環境とuvの話
お疲れさまです。今回は、「他言語での開発経験はあるけれど、Pythonは初めて」という方向けの記事を書きます。ここではPython環境構築でハマったとき、「これを読んで」と渡せる記事を目指しています。読み終わると以下が分かるようになります。
- Pythonの仮想環境とは何か、なぜ必要か
- venvの役割と基本的な使い方
- uvが何をしてくれるのか、venvとの関係
- uv run が何をしているのか
Pythonの環境管理、何が独特なのか
他言語での開発経験があると、Pythonの環境管理で戸惑うことがあります。ここでは、主要な言語と比較しながら、Pythonの環境管理の独特さを説明しましょう。
Node.jsではnpmでパッケージをインストールすると、デフォルトではプロジェクト内の node_modules に入ります。Rubyの bundler も vendor/bundle に gem を入れられます。Javaは Maven や Gradle がプロジェクト単位で依存関係を解決します。PHPのComposerも vendor ディレクトリにライブラリをインストールします。
いずれもプロジェクトごとに依存関係が分離されるのが一般的です。ただし、Pythonの場合は違います。Pythonのパッケージインストーラーである pip でパッケージをインストールすると、デフォルトではシステム全体で共有されるグローバル環境にインストールされます。
| 言語 | 依存管理ツール | デフォルトのインストール先 |
|---|---|---|
| Node.js | npm/yarn | プロジェクト内(node_modules) |
| Ruby | Bundler | プロジェクト単位で分離可能 |
| Java | Maven/Gradle | プロジェクト単位で解決 |
| PHP | Composer | プロジェクト内(vendor) |
| Python | pip | グローバル環境 |
そのため、単純にプロジェクトAでDjango 4.2をインストール( pip install django==4.2 )して、プロジェクトBでDjango 5.0をインストール( pip install django==5.0 )すると、後から入れた方で上書きされます。
これは、Pythonでの環境管理の特徴の一つです。
この問題を解決するのがPythonの仮想環境( venv )です。プロジェクトごとに独立した環境を作り、ライブラリの競合を防ぎます。他言語では当たり前に備わっている「プロジェクト単位の分離」を、Pythonでは仮想環境という仕組みで実現します。
venvとは
venvはPythonに標準で付属している仮想環境ツールです。
python3 -m venv myenv
これを実行すると、 myenv というディレクトリができます。 myenv は任意の名称が設定でき、中にはそのプロジェクト用のPython環境一式が格納されます。 myenv/bin/ にプロジェクト用の python や pip が設置され、 myenv/lib/ にライブラリがインストールされるようになります。
venvの仮想環境を使うには有効化が必要です。macOSの場合は以下のように実行すると仮想環境が有効化されます。
source myenv/bin/activate
仮想環境が有効化されるとシェルのプロンプトに環境名が表示されます。この状態で pip install を実行すると、グローバル環境ではなく myenv 内にライブラリがインストールされます。作業が終わったら deactivate を実行すると、仮想環境を無効化できます。
venv はシンプルな標準ツールなのですが、次のような欠点があります。
- 有効化せずに
pip installするとグローバル環境が汚れる venvそのものは仮想環境を作るだけで、どのライブラリをどのバージョンで入れたかの管理は別で行う必要がある。(requirements.txtといったファイルに書くのが一般的でした)
uvとは
uv はRust製のPythonプロジェクト管理ツールです。Pythonのプロジェクト管理ツールとしては、PoetryやPipenvといった先行ツールがあります。uvは後発で、これらと同様の機能を持ちつつ、Rust製の高速さが特徴です。依存解決やインストールが速いのはもちろんですが、それ以上に「プロジェクト管理を一元化できる」点にメリットがあります。
uvはvenvを置き換えるものではなく、内部でvenv の仕組みを使っています。 uvは、その上でプロジェクトを管理するツールです。次のような機能を内包しています。
- Pythonバージョンの管理
- 依存関係の管理(
pyproject.tomlとuv.lock) - 仮想環境の自動作成と管理
uv では uv add でライブラリを追加できます。これを実行すると、プロジェクト管理用のファイル pyproject.toml に依存関係が記録されます。合わせて、 uv.lock で正確なバージョンが固定されます。別の人も uv sync で同じ環境を復元できます。
uv runの仕組み
さて、本題の「なぜ uv run python と打つのか」について説明します。
通常、 python と打つとグローバルにインストールされているPythonが実行されます。python コマンドで呼び出される Pythonの実態は which python で確認できます。Windowsではwhere pythonになります。以下は実行例です。
> which python
/usr/local/bin/python
仮想環境を使うには、前述のとおり有効化が必要で、忘れたまま pip install すると事故になります。uv run はこの問題を解決します。
uv run python
こう打つと、 uv が管理している仮想環境内のPythonが実行されます。uvが適切な環境でコマンドを実行してくれます。
確認してみましょう。
uv run which python
# /path/to/repository/.venv/bin/python
uv は .venv というディレクトリに仮想環境を作ります。uv run 経由で実行すると、その仮想環境内の python が使われていることが分かります。
python 単体だけでなく、任意のコマンドをuv run経由で実行できます。 uv run pytest 、uv run bash など。
実際の流れ
新しいプロジェクトを始めるときの流れです。
uv init myproject
cd myproject
uv initでプロジェクトが初期化されます。 pyproject.toml が作られます。
uv add django
Djangoをプロジェクトの依存関係に追加します。 pyproject.toml に自動的に記録され、 uv.lock が生成されます。仮想環境がなければ自動で作られ、ライブラリがインストールされます。
uv run django-admin startproject config .
uv run python manage.py runserver
あとは uv run 経由でコマンドを実行します。
既存のプロジェクトをcloneしてきた場合は、uv syncで環境を再現します。
git clone <repository>
cd <project>
uv sync
uv run python manage.py runserver
まとめ
venvはPython標準の仮想環境ツールです。プロジェクトごとに独立した環境を作り、ライブラリの競合を防ぎます。ただしactivateが必要で、忘れると事故のもとになりますし、requirements.txt等を管理する手間も生まれます。
uvはプロジェクト管理を一元化するツールです。内部でvenvを使いつつ、依存関係の管理やPythonのバージョン管理も担います。uv runを使えばactivateを意識せずに仮想環境内でコマンドを実行できます。
uv run python と打つのは、「uvが管理する仮想環境内でPythonを実行する」ためです。