こんにちは!日々のPython開発、快適に進んでいますか?
突然ですが、こんなモヤモヤを抱えたことはありませんか?
「チームで長年使ってきたPoetryのおかげで、PyPIへのパッケージ公開やバージョン管理はすごく安定している。でも……新しい依存関係を追加したり、プロジェクトの環境を一から構築したりするときの依存解決(Resolver)が、とにかく遅い!」
そう、Poetryはその高機能さと引き換えに、依存関係の解決・計算にどうしても時間がかかってしまう宿命があります。特に依存パッケージが数百個を超える巨大なレガシープロジェクトでは、`poetry install`が終わるのをコーヒーを飲みながら待つのが日課になってしまっている方も多いはずです。
そこで今回ご紹介するのが、Rust製で驚異的な速さを誇る次世代パッケージマネージャー `uv` をPoetryの裏側にこっそり組み込み、「Poetryの便利な公開フローはそのままに、インストールと依存解決だけを爆速化する」という現実的かつ極上のハイブリッド運用術です。
これをマスターすれば、毎日の開発で待ち時間が消え失せ、コーディングに集中できる時間が劇的に増えますよ。さあ、一緒にその仕組みを紐解いていきましょう!
—
1. なぜPoetryとuvを混在させるのか?(アーキテクトの視点)
まず、今回の設計思想を整理しておきましょう。
Pythonのパッケージ管理界隈では、「すべてをuvに移行するべきだ」という議論が活発ですが、現実のプロジェクトではそう簡単にはいきません。
- Poetryの強み: `pyproject.toml` の標準的な解釈、`poetry publish` による洗練されたPyPIへのビルド・公開パイプライン、CI/CDとの強固な統合。
- uvの強み: 同期・依存解決・仮想環境作成における、Rustならではの圧倒的な速度(pipやPoetryの10倍〜100倍)。
であれば、「頭脳(依存関係の定義と公開)」はPoetryに担当させ、「筋肉(重くて面倒なファイルのダウンロードと仮想環境構築)」はuvに代行させるのが、最も合理的でリスクの低いアーキテクトの選択となります。
[ pyproject.toml / poetry.lock ]
│
▼ (定義の管理・公開はPoetry)
┌──────────────┐
│ Poetry │
└──────┬───────┘
│ (依存解決の計算結果を渡す)
▼
┌──────────────┐
│ uv │ ==> 爆速で仮想環境へパッケージをインストール!
└──────────────┘
この役割分担をシームレスに行うための具体的なワークフローを、基礎から順番に見ていきましょう。
—
2. 基礎セットアップ:環境の準備
まずは、手元のマシンにPoetryとuvの両方をインストールし、正しく共存させます。すでにPoetryをお使いの方も多いと思いますので、今回はuvの導入と、両者が喧嘩しないための設定にフォーカスします。
ステップ1: 爆速の基盤「uv」のインストール
公式が推奨するインストーラーを使って、uvをシステムに導入します。
macOS / Linux の場合(公式のインストーラーを実行)
curl -sSf https://astral.sh/uv/install.sh | sh
インストールされたことを確認(秒でバージョンが返ってきます)
uv –version
出力例: uv 0.x.x (xxxxxx xxx)
ステップ2: Poetryのプロジェクト構造の確認
お手元に、すでに `pyproject.toml` と `poetry.lock` が存在するレガシー(既存)プロジェクトがあると仮定します。
プロジェクトのルートディレクトリで以下のコマンドを叩いてみてください。
Poetryがプロジェクトの環境をローカル(.venv)に作るように設定
poetry config virtualenvs.in-project true –local
この設定をしておくことで、プロジェクトフォルダの直下に `.venv` という隠しフォルダが生成され、次から紹介する `uv` がその仮想環境をダイレクトに操作できるようになります。ここが共存運用の非常に重要なポイントです。
—
3. HelloWorld的動作確認:爆速環境構築の体感
では、理論はこれくらいにして、実際にどれほど速くなるのかを体感してみましょう。
ここでは簡単な「Hello World」スクリプトが動く環境を、`uv` のパワーを借りて一瞬で構築してみます。
1. サンプル用の `pyproject.toml` を用意する
まだプロジェクトがない場合は、以下の内容で `pyproject.toml` を作成してください。
[tool.poetry]
name = “uv-poetry-hybrid-demo”
version = “0.1.0”
description = “Poetryとuvを混在させた高速開発デモ”
authors = [“Your Name
readme = “README.md”
[tool.poetry.dependencies]
python = “^3.10”
requests = “^2.31.0” # 動作確認用の外部ライブラリ
[build-system]
requires = [“poetry-core”]
build-backend = “poetry.core.masonry.api”
2. Poetryではなく、uvで仮想環境を作成しインストールする!
ここが本記事のハイライトです。通常なら `poetry install` を実行するところですが、代わりに `uv` が持つ仮想環境構築・同期コマンド を使用します。
`uv` は、裏側で `poetry.lock` を自動的に読み取り(あるいはロックファイルがなければ生成し)、数秒でパッケージをインストールしてくれます。
1. 仮想環境がなければuvで瞬時に作成
uv venv –python 3.10
2. poetry.lockの内容をuvを使って爆速で仮想環境に同期(インストール)する
uv pip sync poetry.lock
※注意: `uv pip sync` は poetry.lock を直接解釈できない場合があるため、実務では次に紹介する `Makefile` を使ったスマートな連携フローが王道です。
—
4. 現場で使える現実解:Makefileによる環境スイッチ
手動でコマンドを叩くのはヒューマンエラーの元です。開発チーム全員が同じオペレーションで高速な恩恵を受けられるよう、`Makefile` をプロジェクトに配置するのがプロの現場のやり方です。
プロジェクトのルートに `Makefile` を作成し、以下のコードを記述してください。
Makefile の実装例
.PHONY: install update run
仮想環境のPythonパス
VENV_PYTHON = .venv/bin/python
1. 初回セットアップや依存関係の同期(uvで爆速化)
install:
@echo “==> 仮想環境を確認・作成しています…”
uv venv –python 3.10
@echo “==> Poetryでロックファイルを最新化(必要な場合)…”
poetry lock –no-update
@echo “==> uvを使って爆速で依存パッケージをインストール中…”
# Poetryが管理するrequirements形式に一度エクスポートしてuvに食わせるのが最も確実
poetry export -f requirements.txt –output requirements.txt –without-hashes
uv pip install -r requirements.txt
@echo “==> クリーンアップ…”
rm requirements.txt
@echo “✨ 依存関係の同期が完了しました!”
2. 新しいパッケージを追加する時(Poetryの安全な依存解決を使用)
例: make add pkg=fastapi
add:
@echo “==> Poetryで安全にパッケージを追加中: $(pkg)”
poetry add $(pkg)
@echo “==> 追加された内容をuvで即座に環境へ反映…”
poetry export -f requirements.txt –output requirements.txt –without-hashes
uv pip install -r requirements.txt
rm requirements.txt
@echo “✨ パッケージの追加とインストールが完了しました!”
3. 動作確認スクリプトの実行
run:
@echo “==> アプリケーションを実行します…”
$(VENV_PYTHON) main.py
このMakefileがもたらす圧倒的なメリット
1. 依存関係の追加・解決 (`make add pkg=xxx`): 複雑な依存関係の計算やバージョン競合のチェックは、安全な Poetry に任せます。これにより、予期せぬバージョンのバグを防ぎます。
2. インストールの実行 (`make install`): 計算された `poetry.lock` をもとに、重いダウンロードと配置作業を uv が数秒で終わらせます。
—
5. 動作確認用スクリプト(main.py)の作成
環境が正しく構築できているか確認するため、`requests` ライブラリを使った簡単な `main.py` を作成して実行してみましょう。
main.py
import sys
import requests
def main():
print(f”Python Version: {sys.version.split()[0]}”)
print(“外部ライブラリを通じた通信テストを実行します…”)
# Public APIにリクエストを投げてみる
response = requests.get(“https://api.github.com”)
if response.status_code == 200:
print(“🎉 成功!uvとPoetryが共存する環境で、requestsが正常に動作しています。”)
else:
print(f”⚠️ 予期せぬステータスコードです: {response.status_code}”)
if __name__ == “__main__”:
main()
実行してみる
先ほど作成した `Makefile` を使って、一連のフローをテストします。
依存関係のインストール(uvの爆速さを体感!)
make install
アプリケーションの実行
make run
コマンドを実行した瞬間、あまりの処理の速さに驚かれるはずです。「え、もう終わったの?」と声が出るほどのスピードで仮想環境へのインストールが完了し、綺麗に `main.py` が成功メッセージを吐き出すはずです。
—
6. まとめ:レガシーの安心感と、最新のスピードを両立する
いかがでしたでしょうか?
今回は、レガシーなPoetryプロジェクトの資産と安心感をそのままに、日々の開発体験を劇的に改善する「Poetry + uv ハイブリッド運用術」を解説しました。
- 依存関係の計算とパッケージの公開(CI/CD含む) = Poetry
- 重たいダウンロード・仮想環境への同期・インストール = uv
この「適材適所」の役割分担をMakefileでラップしてチームに共有するだけで、チーム全体の開発ストレスはゼロになり、CI/CDのビルド時間短縮によるクラウドコスト削減にも直結します。
「レガシーだから新しいツールは導入できない」と諦める必要は一切ありません。今日からこのワークフローを取り入れて、ストレスフリーで圧倒的に高速なPythonライフを満喫してくださいね!