【実務・中級編】uvの実験的機能「uv run」を使いこなす:スクリプト実行時に依存関係をインライン指定する魔法 – ビルド・パッケージ管理ツール生産性向上バイブル

こんにちは。テックリードの私だ。

日々の開発において、「ちょっとしたデータ加工用のスクリプトを書きたい」「CSVをJSONに変換するワンライナーをチームメンバーに共有したい」というシーンは数多く存在する。しかし、これまではどうだったか?

1. 適当なディレクトリを作る
2. `python -m venv .venv` で仮想環境を構築する
3. `source .venv/bin/activate` で有効化する
4. `pip install pandas requests` で依存関係を入れる
5. やっとコードを書き、実行する
6. 終わったら `.venv` の存在を忘れ、ディスク容量を圧迫していく…

この儀式、もう終わりにしよう。

Astral社が開発したRust製の爆速パッケージマネージャ `uv` が持つ実験的機能 `uv run` と、Pythonの標準規格 PEP 723 を組み合わせれば、単一の `.py` ファイルの中に依存関係を閉じ込め、仮想環境の構築すらスキップして一撃で実行できる。

今回は、この「インライン依存関係管理」のメカニズムを紐解き、チームの生産性を限界突破させる実践テクニックを全公開する。

—

1. なぜ `uv run` なのか?(内部アーキテクチャの理解)

従来の `pip` や `poetry` は、「環境(Environment)」と「コード(Code)」を分離して管理するアプローチをとってきた。そのため、コードを実行する前に必ず環境のセットアップが必要だった。

一方、PEP 723で規定されたインラインメタデータは、「スクリプト自体が自身の依存関係を定義する」というパラダイムシフトをもたらす。

内部で何が起きているのか?

1. `uv run script.py` を実行すると、`uv` はスクリプトの先頭にあるコメントブロック(PEP 723形式)をパースする。
2. 宣言されている依存関係(例: `requests`, `pandas`)を読み取る。
3. ユーザーのホームディレクトリ配下のグローバルキャッシュとリンクし、ミリ秒単位で一時的な仮想環境(Ephemeral Environment)をオンザフライで構築・解決する。
4. その環境上でスクリプトを実行し、終了後は環境を適切にハンドリングする(あるいはキャッシュとして再利用する)。

これにより、開発者は「環境の管理」という認知負荷から完全解放される。

—

2. 実践:PEP 723 に準拠したスクリプトの書き方

百聞は一見にしかず。実際に依存関係をインラインで記述したスクリプトを作成しよう。

以下のコードを `analyze_log.py` という名前で保存してほしい。

/// script
requires-python = “>=3.11”
dependencies = [
“requests>=2.31.0”,
“rich>=13.0.0”,
]
///

import requests
from rich import print
from rich.panel import Panel

def fetch_system_status() -> None:
“””外部APIからステータスを取得し、リッチなUIでコンソールに描画する”””
# ダミーのパブリックAPIを叩く想定
response = requests.get(“https://httpbin.org/json”)
data = response.json()

# richライブラリによる美しく見やすい出力
print(Panel(str(data), title=”[bold green]API Response Success[/bold green]”, expand=False))

if __name__ == “__main__”:
fetch_system_status()

このコードのポイント

  • `# /// script` から `# ///` までのブロック: ここがPEP 723で定められたTOML形式のメタデータ領域。Pythonのパーサからは単なるコメントとして無視されるが、`uv` などの対応ツールからは厳密な設定として解釈される。
  • `dependencies`: このスクリプトを動かすために必要なサードパーティライブラリをピンポイントで指定。バージョン制約も通常の `pyproject.toml` と同様に記述できる。

—

3. 爆速実行コマンドと裏技ワークフロー

作成したスクリプトを実行するには、以下のコマンドを叩くだけだ。

uv run analyze_log.py

たったこれだけで、手元に `venv` ディレクトリを作ることなく、`uv` が自動的に `requests` と `rich` の依存関係を解決・インストールし、スクリプトを実行してくれる。2回目以降の実行は、キャッシュが効くため一瞬(0.1秒未満)で起動する。

さらにスマートに:shebang(シバン)の活用

LinuxやmacOS環境であれば、スクリプトの先頭にshebangを記述することで、シェルスクリプトやバイナリと同じように直接実行できるようになる。

`analyze_log.py` の最上行に以下を追加する。

!/usr/bin/env -S uv run
/// script
requires-python = “>=3.11”
dependencies = [
“requests>=2.31.0”,
“rich>=13.0.0”,
]
///
…

実行権限を付与すれば、もはや `uv run` すら打つ必要がない。

実行権限を付与
chmod +x analyze_log.py

直接実行(内部で自動的に uv run が呼び出される)
./analyze_log.py

—

4. チーム開発を加速させる応用テクニック

この機能は、単発のスクリプト実行にとどまらず、チーム全体の開発フローを劇的に改善する。

A. メンテナンス性の向上:依存関係の自動追加・更新

「あとから新しいライブラリ(例えば `pandas`)を使いたくなった」という場合、手動でコメントブロックを書き換える必要はない。`uv` のコマンドを使ってインラインメタデータを安全に操作できる。

スクリプトに直接依存関係を追加する(PEP 723ブロックを自動更新)
uv add –script analyze_log.py pandas

このコマンドを実行すると、`analyze_log.py` 内の `# dependencies` リストに自動的に `”pandas>=…”` が追記される。手動編集による構文ミスを防ぐための極めて重要なプラクティスだ。

B. CI/CDパイプラインやタスクランナーでの活用

GitHub ActionsなどのCI環境において、複雑なセットアップステップを排除できる。

.github/workflows/data_check.yml の抜粋
steps:

  • uses: actions/checkout@v4
  • name: Install uv

uses: astral-sh/setup-uv@v5

  • name: Run maintenance script without manual venv setup

run: uv run scripts/verify_database.py

CI側で `pip install -r requirements.txt` を実行するオーバーヘッドが消え、ワークフローの実行時間が大幅に短縮される。

—

5. テックリードからの推奨設定(ベストプラクティス)

`uv` をチームで本格導入するにあたり、リポジトリルートに配置すべき設定ファイル `uv.toml` の実用的な構成例を共有する。

`uv.toml`(プロジェクト共通設定)

ワークスペースやグローバルな振る舞いを制御する設定ファイル

キャッシュのディレクトリを明示的に指定したい場合(CI環境など)
cache-dir = “~/.cache/uv”

Pythonのダウンロードソース(Astral社が提供する最適化されたビルドを使用)
python-preference = “managed”

[pip]
レガシーなpipとの互換性を維持しつつ、高速なインポートを強制
compile-bytecode = true

—

総括

`uv run` と PEP 723 インライン依存関係は、Pythonにおけるスクリプト実行の概念を根底から覆すキラー機能だ。

  • 「環境汚染」の恐怖からの解放
  • 「READMEのセットアップ手順が長すぎる」という問題の解決
  • 「ちょっとしたコード共有」の圧倒的な手軽さ

今日のタスクから、使い捨てのスクリプトには仮想環境を作るのをやめ、インラインメタデータを書いて `uv run` を使ってみてほしい。開発スピードが一段階跳ね上がる感覚を、ぜひチーム全体で体感してほしい。

タイトルとURLをコピーしました