Lean Baseball

No Engineering, No Baseball.

個人開発プロジェクトのPythonライブラリ管理をpoetryからuvに移行した話

本業はSRE, 相変わらず野球関係の趣味開発(個人開発)をしている者です.

今まで趣味開発におけるPythonのPackage Managerはpoetryを使っていましたが, 仕事で使っている&その他の理由でuvに変更しました.

github.com

このブログではそんなuvの話を書きたいと思います.

このブログについて

弊ブログ「Lean Baseball」では初の試みとして, 執筆の大半をCursorで行っています*1.

なお以下については中の人(shinyorke)の執筆となります.

  • 挨拶など, 人間っぽい言い回しと脚注
  • GitHub Actionsのコードスニペット
  • サムネイルなどの画像
  • 明らかな間違い, 見当違いっぽい内容

TL;DR

poetryからuvへの移行は学習コストが思ったより低かったです, パッケージのインストールとテストの実行が高速化された(気がします). 一方で, pyproject.tomlの書き換えやCIテストの移行にはやや苦労ししました.

移行の背景とメリット

Pythonのパッケージマネージャーとしてpoetryを使用していましたが, 以下の理由からuvへの移行を決断しました.

  • 仕事のプロジェクトで使っているから(最大の理由*2
  • なんか流行っているっぽいから(2番目の理由)

移行は若干苦労しましたが, 開発効率的にもコードの見通し的にもスッキリした気がします.

学習コストの低さ

uvはpoetryと同様のコマンド体系を持っているため, 学習コストは非常に低かったです. 例えば, 以下のようなコマンドはほぼ同じように使用できます.

# poetryの場合
poetry add pandas
poetry install
poetry run pytest

# uvの場合
uv add pandas
uv install
uv run pytest

ドキュメントを読んだ感じの雰囲気も察していましたが...想像以上に楽でした.

パフォーマンスの向上

uvはRustで実装されており, 以下の点で高速化が実現できました.

  • 雰囲気的にtestやツール類の実行が速くなった気がする
  • GitHub Actionsのtask実行は明確に高速化

こちらは導入前後のCI速度を見ると歴然でした.

差は歴然だった

移行で苦労した&変更した所

移行作業では以下で苦労したり変更したりしました. それぞれの課題に対して, どのように対処したかを説明します.

  • pyproject.tomlの書き換え
  • コードチェックをruffに変更

pyproject.tomlの書き換え

poetryの設定ファイルからuv用の設定ファイルへの移行には若干手間がかかりました.

  • poetry用のpyproject.tomlを別名保存
  • uvのpyproject.tomlをゼロから作成
  • 元のpoetry用pyproject.tomlを見ながらライブラリを追加

今回はPythonで作ったAPI・workerバックエンドが3つありましたがすべてに対して愚直にこれを行ってテストしました.

今回はuvを覚えるために「あえて」AIに頼らず手動でやりましたが, 次からはCursorに頼って試そうと思っています.

コードチェックをruffに変更

一言で言うとruffに変更しました.

  • type checkはmypy
  • コードのチェックほかはruff

isort, blackはいいだろうと言うことで捨てました&mypyも無くて良かったかも(ruffでチェックしているっぽいので).

何をどう変更したかはGitHub Actionsの移行をご覧ください.

GitHub Actionsの移行

CI/CDパイプラインの移行も重要な作業でした. poetryからuvへの移行に伴い, GitHub Actionsのワークフローファイルも大きく変更しました.

主な変更点

移行前後のGitHub Actionsの設定を比較すると, 以下のような変更がありました.

  1. パッケージマネージャーのセットアップ

    • poetry: abatilo/actions-poetry@v2.0.0を使用
    • uv: astral-sh/setup-uv@v5を使用
  2. 依存関係のインストール

    • poetry: poetry installでシンプルにインストール
    • uv: uv sync --all-extras --devで開発用の依存関係も含めて一括インストール
  3. コード品質チェックツールの統合

    • poetry: black, isort, mypyを個別に実行
    • uv: ruffに統合し, format, checkを一括で実行

設定ファイルの比較

移行前(poetry)の設定:

  dashboard-test:
    name: Dashboard Test
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: "${{ env.ROOT_PATH_DASHBOARD }}"  
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: 3.12.5
      - id: use-poetry
        name: Run image
        uses: abatilo/actions-poetry@v2.0.0
        with:
          poetry-version: "1.8.3"
      - id: poetry-install
        name: Install & test
        run: poetry install
      - id: type-check
        name: type check
        run: poetry run mypy .
      - id: code-check
        name: code check
        run: poetry run black .
      - id: import-check
        name: import check
        run: poetry run isort .
      - id: run-test
        name: Run test
        run: poetry run pytest .

移行後(uv)の設定:

  dashboard-test:
    name: Dashboard Test
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: "${{ env.ROOT_PATH_DASHBOARD }}"  
    steps:
      - uses: actions/checkout@v4
      - id: install-uv
        name: Install uv
        uses: astral-sh/setup-uv@v5
      - id: setup-python
        name: "Set up Python"
        uses: actions/setup-python@v5
        with:
          python-version-file: "${{ env.ROOT_PATH_DASHBOARD }}/pyproject.toml" 
      - id: install-project
        name: Install the project
        run: uv sync --all-extras --dev
      - id: format
        name: code format
        run: uvx ruff format .
      - id: type-check
        name: type check
        run: uvx mypy .
      - id: code-check
        name: code check
        run: uvx ruff check . --fix --output-format=github
      - id: run-test
        name: Run test
        run: uv run pytest .

主な差分:

   steps:
     - uses: actions/checkout@v4
-    - uses: actions/setup-python@v5
-      with:
-        python-version: 3.12.5
-    - id: use-poetry
-      name: Run image
-      uses: abatilo/actions-poetry@v2.0.0
-      with:
-        poetry-version: "1.8.3"
+    - id: install-uv
+      name: Install uv
+      uses: astral-sh/setup-uv@v5
+    - id: setup-python
+      name: "Set up Python"
+      uses: actions/setup-python@v5
+      with:
+        python-version-file: "${{ env.ROOT_PATH_DASHBOARD }}/pyproject.toml"
-    - id: poetry-install
-      name: Install & test
-      run: poetry install
+    - id: install-project
+      name: Install the project
+      run: uv sync --all-extras --dev
-    - id: type-check
-      name: type check
-      run: poetry run mypy .
-    - id: code-check
-      name: code check
-      run: poetry run black .
-    - id: import-check
-      name: import check
-      run: poetry run isort .
+    - id: format
+      name: code format
+      run: uvx ruff format .
+    - id: type-check
+      name: type check
+      run: uvx mypy .
+    - id: code-check
+      name: code check
+      run: uvx ruff check . --fix --output-format=github
     - id: run-test
       name: Run test
-      run: poetry run pytest .
+      run: uv run pytest .

この変更により, CIの実行時間が結構短くなりました.

移行の手順

実際の移行手順は以下の通りです. 各ステップで注意すべき点を詳しく説明します.

  1. 既存のpoetry環境のバックアップ

    • pyproject.tomlpyproject-poetry.tomlにリネーム
    • この時点でpoetry.lockpoetry.tomlは残しておく
    • バックアップを取ることで, 万が一移行に失敗した場合でも元の環境に戻せる
  2. uvの初期化

    • uv initコマンドで新しいpyproject.tomlを作成
    • この時点でpyproject.tomlは最小限の設定のみが含まれる
    • プロジェクト名やバージョンなどの基本情報は自動的に設定される
  3. 依存関係の移行

    • pyproject-poetry.tomlを参考に, 必要なライブラリをuv addコマンドで追加
    • 開発依存関係はuv add --devで追加
    • バージョン指定が必要な場合はuv add package==versionの形式で指定
    • 依存関係の解決に失敗した場合は, エラーメッセージを確認して必要な調整を行う
  4. GitHub Actionsの更新

    • poetryの設定をuvの設定に置き換え
    • ruffの設定を追加し, コード品質チェックを統合
    • テスト実行コマンドをuv run形式に変更
  5. 移行完了後のクリーンアップ

    • 移行が完了し, すべてのテストが正常に動作することを確認
    • 以下のファイルを削除
      • pyproject-poetry.toml
      • poetry.lock
      • poetry.toml
    • 削除前に, これらのファイルの内容を確認し, 必要な設定がpyproject.tomlに反映されていることを確認

結び

poetryからuvへの移行は, 多少の苦労はありましたが, 全体的に見れば成功だったと考えています.

開発体験的にも悪くないのと, 何よりも仕事で使っているモノに変更できたお陰で一石二鳥感もあったりします.

おそらく今後はpoetryは使わない(使う理由が無い)気がしています, ずっとuvなのかと言われるとそこも違う気がしますが...

以上, 「個人開発プロジェクトのPythonライブラリ管理をpoetryからuvに移行した話」でした.

最後までお読みいただきありがとうございました.

おまけ - Cursorはどこまでブログを書いたか

見ての通り, 結構な所をやってくれました.

緑の部分はshinyorkeが修正・加筆した所.

*1:これは別エントリーで明言する予定ですが, このLean Baseballというブログ, noteおよび会社関係の発信も徐々に生成AIに寄せていきます. 目指せブログ執筆の自動運転.

*2:理由の9割がこれ