- uvを使うと、Pythonスクリプト実行時の依存関係管理を自動化できる
- 別途仮想環境を管理しなくても、スクリプトごとに環境が自動で作成・維持される
- 必要なパッケージはinline metadataやコマンドラインオプションなど、さまざまな方法で宣言できる
- Pythonバージョンやパッケージ管理もスクリプト単位で宣言でき、自動で調整される
- Lockファイルや依存関係のバージョン制限オプションにより、再現性と保守性を高められる
概要
- uvは、Pythonスクリプト実行時にそのスクリプトが必要とするパッケージ依存関係を自動で管理してくれるツール
- ユーザーは面倒な仮想環境の作成やパッケージのインストールを自分で行う必要がない
- 複数の実行オプションやinline metadataの活用方法、さまざまな依存関係の宣言方法、各種制御機能を提供する
Python環境とuvの役割
- Pythonは、それぞれのインストールごとに固有の環境を持つ
- 一般的には仮想環境を作成して管理することが推奨される
- uvは仮想環境を自動で管理し、宣言的な方法で依存関係を扱う
- シンプルなスクリプトなら
uv run example.pyだけですぐに実行できる
- 標準ライブラリのみを使う場合は追加設定なしで動作する
引数の受け渡しと入力方法
- スクリプトにコマンドライン引数を渡せる
- 標準入力から直接スクリプトコードを受け取って実行したり、here-document機能も利用できる
プロジェクト環境と--no-projectオプション
- スクリプトがプロジェクトフォルダー(例:
pyproject.tomlがある場所)で実行される場合、プロジェクトの依存関係もインストールされる
- 不要であれば、
--no-projectフラグをスクリプト名の前に置くことで、プロジェクト環境を無視できる
スクリプト依存関係の宣言と管理
- 外部パッケージが必要な場合、コマンドラインオプション
--withを使って依存関係を指定して実行できる
- 特定のバージョン制約にも対応し、複数の依存関係もオプションを繰り返して指定できる
- プロジェクト環境に追加の依存関係を加えることもでき、不要なら
--no-projectで制御できる
Inline Script Metadata(PEP 723方式)
- Pythonでは、スクリプト自体に依存関係やPythonバージョンを宣言するための標準フォーマットが利用できるようになった
uv init --scriptで、インラインメタデータを含むスクリプトを簡単に生成できる
uv add --scriptで、スクリプトに必要な依存関係をTOML形式で追加・管理できる
- インラインメタデータがある場合、プロジェクトの依存関係は無視され、スクリプトの依存関係だけが適用される
Pythonバージョンの宣言と管理
- スクリプト内または実行時に、使用したいPythonバージョンを指定できる
- 指定されたバージョンがない場合は、自動でダウンロードおよび設定される
Shebangでそのまま実行できるスクリプトの作成
- shebang(
#!...)を使えば、uv run --script方式で直接実行可能なファイルを作成できる
- この場合も、依存関係の宣言やPythonバージョンなどをスクリプト先頭で指定できる
パッケージインデックスと認証のサポート
--indexオプションでカスタムパッケージインデックスを利用できる
- index情報もメタデータに含められる
- 認証が必要な場合は、別途ドキュメントを参照できる
依存関係の固定(Lock)と再現性の向上
uv lock --scriptでスクリプト単位のLockファイルを作成・管理できる
- その後の実行や依存関係追加時にはLockファイルが再利用され、必要に応じて更新される
- バージョン再現性のための
exclude-newer(特定の日付以降のリリースを除外)オプションを提供する
- 日付はRFC 3339タイムスタンプで指定する
Pythonバージョンの柔軟性
- 実行のたびにコマンドラインオプションで任意のPythonバージョンを指定して利用できる
- 例:
uv run --python 3.10 example.py
Windowsサポート
.pyw拡張子を持つスクリプトは、Windowsでpythonwとして実行される
- GUIベースのスクリプトも依存関係とともに実行できる
参考ドキュメント
- より詳しいコマンドの使い方は、CLIリファレンス文書およびツールの実行・インストールガイドを参照できる
結論
- uvは、Pythonスクリプトの実行環境、依存関係、バージョン、パッケージインデックス、再現性などを自動かつ簡単に管理し、生産性と信頼性を同時に高めてくれるツール
7件のコメント
私も
pipからuvに乗り換えてみましたが、本当に速度が速いという一点だけでも乗り換える価値があるレベルでしたよく話題に上がっていたので昨日初めて使ってみましたが……本当に速いですね。うわ……
uv関連の投稿、ここでもう5本以上見た気がします;;;
ほかの機能はさておき、単純に速度だけでも使う理由は十分あります。
もう一度 pip を使えと言われても、絶対に無理なくらいです。
conda のシステムパッケージ管理は flake.nix に置き換えて使っていますが、共同作業や既存の conda+pip で保守されていたプロジェクト以外では、個人的には今後 uv+nix を使っていくことになりそうです。
Uv - Rustで実装された超高速なPythonパッケージングツール
UVを活用してPython開発ワークフローを革新する
uvとPEP 723でPythonスクリプトを活用する
uvを1年間使ってみた: 長所・短所と移行時に考慮すべき点
最近、Pythonの実行の大半を
uvに置き換えましたが、本当に高速です。完全には互換性のない高度な機能がいくつかあるものの、ほとんどの場合はほぼ同じように動作します。
Hacker Newsのコメント
「スクリプト依存関係の宣言」機能が本当に便利だと実感した。
公式ガイド文書で紹介されているように、次のように Python コードの先頭にコメントで依存関係を記述できる。
このファイルを
script.pyとして保存し、uv run script.pyで実行すると、指定した依存関係が魔法のように一時的な仮想環境へインストールされ、そのまま実行できる。これは Python の PEP 723 を実装したもので、Claude 4 もこのトリックを知っているので、「インラインのスクリプト依存関係を含む Python スクリプト」を書いてとプロンプトすれば、正しく作ってくれる。
たとえば、httpx と click を使って大容量ファイルをダウンロードし、進捗バーを表示するコードの作成を依頼できる。
Claude 4 以前は、この種の機能を使うには専用プロジェクトや別途の説明が必要だったが、今はそうではない。
詳しいユースケースも参考になる。
shebang モードも本当に便利だと感じる。
以下のようにスクリプトの 1 行目に shebang を追加すれば、
./script.shのように実行できる。requirementsファイルと同じ形式だったらよかったのに、と思う。そうであれば、uv がないユーザー向けに、簡単なコメントで pip から同じようにインストールできるワンライナーも提示できるからだ。
たとえば
pip install -r <(head myscript.py)のようなアプローチが可能になりそうだ。実際、PEP 723 は最近注目されている uv だけでなく、pipx や hatch でもサポートされている。
また、pip-tools などもサポートのロードマップに含まれている。
(関連 issue参照)
初めて見たとき、requests の横にあるのがハートの絵文字だと思ったことがある。
この方式は本当にすばらしいと思う。
ただ、いつかはマジックコメントではなく、組み込みの言語構文として採用されてほしい。
コメントは少し雑然として見える。
もちろん、ツール側から見ればマジックコメントのほうがパースしやすく、Python コアがパッケージングの知識をあまり持っていないなどの構造的な事情があることも分かるが、いつかは組み込み構文があってほしい。
このやり方には共感する。
Python では
requirements.txtファイルが必須ではないが、管理を怠ると機能が壊れる不便さがよく起きるのが惜しい。関連ツイート参照。
この方式で遭遇した落とし穴を共有したい。
インターネットが切れたときにルーターを再起動するスクリプトに使ったのだが、依存関係のインストール動作がインターネット接続に依存するため、ネットワークが使えないとスクリプト自体が動かなくなる問題があった。
事前に気づいて依存関係の事前インストールで解決したが、自分のようなミスをしないよう、本当に airgapped な環境(ネットワークが完全に遮断された環境)では使わないことを勧める。
uv のキャッシュがあってもキャッシュミスは起こりうる。
uv run --offlineオプションを使うと、キャッシュ済みの依存関係を使って新バージョンの確認なしに実行できる。同じ機能は
uvxでも使える(uvx --offline ...)。依存関係や venv を使う必要があるなら、少なくとも一度はインターネット接続のある状態で実行しておく必要があり、その後でオフラインでも使える仕組みだと理解している。
最近の Python エコシステムでは、いろいろな機能がだんだんとうまく噛み合ってきているように感じる。
Marimo と uv のスクリプト依存関係の組み合わせで、別チームでも使いやすい再現可能なレポート/診断ツールを作り始めている。
uv のこの機能がいちばん気に入っていて、そのために uv に乗り換えた。
複数の git-hooks スクリプトがそれぞれ別の依存関係を持っていたが、それらをメインの venv に入れたくなかった。
#!/usr/bin/env -S uv run --script --python 3.13を 1 行追加するだけで、開発者にはbrew install uvと案内すれば済み、別途 venv を作らなくてもスクリプト内でそのまま使えるようになった。-Sフラグがなぜ必要なのか知っている人はいるだろうか。自分の BSD 環境では
/usr/bin/env -S uv run --python 3.11 pythonでも/usr/bin/env uv run --python 3.11 pythonでも Python shell が起動して、結果は同じように見えた。env のマニュアルを見ても明確には読み取れなかったので、有用な情報があれば知りたい。
(ここでの
-Sは引数を空白で分割する役割。)UV のおかげで、もともとは Python の大規模な移行作業を golang でやるつもりだったが、その移行範囲を縮小できた。
とくに小さなスクリプト形式の作業は、もう移行する必要がなくなった。
この機能は本当に「キラー機能」だと確信している。
依存関係に Pytorch が含まれる場合、この方式は少し制約があるかもしれない。
uv は Pytorch 向けの 統合サポート をうまく提供しているが、スクリプトヘッダーだけでは、どの wheel index(CPU、CUDA、ROCm など)が最適かを明確に選ぶ方法がないのが惜しい。
uv が自動で作成する venv を VS Code が簡単に認識できればいいのに、と思う。
今は Python extension がサードパーティの import をすべて赤線で表示してしまう。
暫定的な回避策として uv の Cache ディレクトリから手動で venv のパスを探して登録しているが、venv が頻繁に再生成されるとまたやり直しになるので面倒だ。
uv python find --script "${filePath}"コマンドで env のパスを見つけられる。その機能を VS Code 上で自動検出して有効化する 拡張機能 を開発中だ。
uv のこの機能がとても気に入っている。
jupyter notebook も別途インストールせず、次のようにワンライナーで実行できる。
すべてが一時的な仮想環境にインストールされ、その後はきれいに片付けられる。
プロジェクト内で実行した場合は、そのプロジェクトの依存関係も自動で認識する。
ただし、完全に「きれいに」片付くわけではなく、uv のキャッシュフォルダはどんどん大きくなりうる。
自分も
uv run --with ipython --with boto3 ipythonのようによく使っていて、本当に時間の節約に大きく役立っている。最近
uv runまわりで見つけたちょっとした issue がある。スクリプトをプロジェクトフォルダの外から実行すると、実際のスクリプトファイルの場所ではなく、現在の作業ディレクトリから
pyproject.tomlを探す挙動がある。そのため、依存関係を
pyproject.tomlに保存したスクリプトは、uv run path/to/my/script.pyのように外部から実行すると正しく動かないことがある。この現象は、常にインライン依存関係を使うか、
--project引数を使えば解決できるが、script のパスを 2 回入力しなければならず不便だ。uv 自体は非常にすばらしいが、この小さな特性はかなり不便に感じる。
uv 専用の shebang とスクリプト内依存関係の方式を満足して使っていた。
さらに
uv lock --script example.pyコマンドで、そのスクリプト 1 本専用の lock ファイルまで作れる点が、いっそう印象的だ。Python パッケージングは 20 年以上続いてきたのに、こんなに自然な体験がようやく登場したことに驚いている。
私たちの組織では、lockfile の依存関係を
trivy fs uv.lockなどでスキャンし、既知の CVE を含むコードの実行を防ぐ用途にも活用している。