🍽️

(多分)読むだけでわかるuvでのプロジェクト管理

に公開

はじめに

こんにちは!KGモーターズ株式会社でエンジニアをしている中村です。

KGモーターズは、広島を拠点に1人乗り小型 EV mibot を開発しているスタートアップです。

KGモーターズでは現在量産に向けて

  • アプリ開発
  • インフラ・クラウド開発
  • 制御開発

がメインで走っていますが、将来の仕込みとしてmibotの自律化に向けた開発も進めています。
AI・機械学習の開発となるとほとんどがPythonになりますが、今回はPythonの開発を効率よく進められるパッケージ管理ツールのuvについてです。

https://docs.astral.sh/uv/

私自身これまでPoetryをメインに使っていましたが、この1年くらいでuvをよく目にするようになって、使ってみた結果

  • 早い!
  • 便利かも!

ということでテックブログに残しつつ、できれば社内標準にしたいと思っています...

前提

以下を前提とします。

  • Mac環境での環境構築
  • Pythonのパッケージ管理についてはなんとなく知ってる

uvとは

uvを話す前にその他の管理ツールについて簡単におさらい...

これまでの管理ツールについて

ここで詳細を挙げるとキリがないのですが、よく使われるものを記載します。

pip

  • Pythonに標準で付属するインストーラ
  • PyPI (Python Package Index) から公開パッケージをインストールする方法
  • pip install パッケージ名のようにコマンド一つでインストールできる
  • 仮想環境の作成や依存関係の固定(ロック)機能は含まれていない
  • プロジェクトごとに環境を分ける場合はvenvなどと併用して使う必要がある

venv

  • Python標準の仮想環境作成モジュール
  • python -m venv env名でプロジェクト専用のディレクトリ(仮想環境)を作り、その中にpipでパッケージをインストールすることで、グローバル環境とは切り離された依存関係管理を実現

poetry

  • わりと最近主流となっていたパッケージ管理ツール
  • pyproject.toml内に依存パッケージやメタデータ、フォーマッターなどの設定を宣言
  • poetry installで仮想環境の作成、依存関係の解決、インストールまで行う
  • poetry.lockファイルというロックファイルをGit管理して再現性を担保する
  • 処理速度はやや重め

で、uvは?

仮想環境作成、バージョン管理がオールインワンでできます。
そしてRust製で早いのが特徴です。
雑に言えば速度がめっちゃ早いpoetryみたいな感じです。


https://docs.astral.sh/uv/

環境構築

公式を参照して一発で終わります。

$ curl -LsSf https://astral.sh/uv/install.sh | sh

チェックしましょう。

$ uv --version
uv 0.8.22 (ade2bdbd2 2025-09-23)

# もしくは
$ uv self version
uv 0.8.22 (ade2bdbd2 2025-09-23)

使い方

初期化

公式に従ってやってみましょう。

$ uv init test

上記を実行するとtestフォルダが生成され、その中は以下のようになっています。

test/
├── .gitignore
├── .python-version
├── main.py
├── pyproject.toml
└── README.md

一応ファイルたちの解説↓

  • .gitignore
    • Gitで追跡しないファイルやフォルダを記載するためのファイル
    • 新規プロジェクトだと言語に応じてGitignore.ioで生成したりします
  • .python-version
    • このプロジェクトでのPythonのバージョンを記載するファイル
    • pyenvを使ったことがある人にはお馴染みのもの
  • main.py
    • ありがた迷惑(?)でつけてくれているサンプルの実行ファイルっぽいです
  • pyproject.toml
    • Poetryではお馴染みのパッケージ管理やメタデータを記述するファイル
    • これをもとにlockファイルを生成し、依存解決をする
  • README.md
    • ありがた迷惑(?)でつけてくれているREADME...

ということでまあまあ余計なものもありますが、これをもとに進めていきましょう。

仮想環境の作成

先ほどのtestフォルダに移動しておきます。

$ cd test

では仮想環境を作成します。以下を実行すると.venvフォルダができます。

$ uv venv

またバージョンを指定して環境を作ることもできます。

$ uv venv --python 3.11

uvではpythonのバージョンを以下のようにインストールしたり指定したりできます。

# インストール
$ uv python install 3.xx

# インストール済みバージョンチェック
$ uv python list

# カレントプロジェクトで使用するバージョンの指定
$ uv python pin 3.11

ライブラリの追加・削除

poetryユーザーは特に違和感ないでしょう。

  • 追加
$ uv add ライブラリ名
  • 削除
$ uv remove ライブラリ名

実行時

これもpoetryユーザーは特に違和感ないでしょう。
実行前に仮想環境が自動で作成&更新され、依存関係もアップデートされるみたいです!(すごい)

$ uv run python main.py
# または
$ uv run main.py

uvxコマンド

uvx は CLI やパッケージを一時的な環境で素早く実行できるコマンドです。ネットで調べるとpytest の例を見かけますが、pytest はどう考えてもプロジェクトに入ってるのでは...と思ったので、クイックにリンターを使いたい場合は以下のようになります。

$ uvx flake8

その他

  • 依存関係の同期
$ uv sync
  • ロックファイルの更新
$ uv lock
  • 依存関係のツリーを表示
$ uv tree

ユースケース別のTips

src-layoutでの設定方法

トップレベル直下の src をパッケージにする構成を考えます。
src-layoutと呼ばれるやつで、例えば以下の構成で、エントリーポイントの下に src がないのでsrc をパッケージにしないといけません。

.
├── src/
│   ├── __init__.py
│   └── XXX.py
└── tools/
    └── main.py -> ここがエントリーポイントになる

Poetryでは独自の [tool.poetry] セクションを持っており、packages = [{ include = "src" }] というシンプルな指定で済みます。

[tool.poetry]
...
packages = [
  { include = "src" }
]

一方 uv では setuptools にビルド役になってもらいます。

# setuptoolsでビルド/インストールしてと合図
[build-system]
requires = ["setuptools>=69", "wheel"]
build-backend = "setuptools.build_meta"


...
# src/をパッケージとして含めるよう setuptools に指示
[tool.setuptools]
packages = ["src"]

公式にも以下の記載があります。

uv uses the presence of a build system to determine if a project contains a package that should be installed in the project virtual environment. If a build system is not defined, uv will not attempt to build or install the project itself, just its dependencies. If a build system is defined, uv will build and install the project into the project environment.

日本語にすると

uv は、ビルドシステムの有無を見て、そのプロジェクトが仮想環境にインストールすべきパッケージを含んでいるかどうかを判断します。もしビルドシステムが定義されていなければ、uv はプロジェクト自体をビルド・インストールせず、依存関係だけを扱います。
逆にビルドシステムが定義されていれば、uv はプロジェクト自体をビルドしてプロジェクト環境にインストールします。

Github Actionsで使う

これもよくあるケースですが、uvで作った仮想環境で開発しているので、CIも同じ環境で走らせる必要があります。
ミニマムでuvを使ったworkflowを作るとこんな感じです。

実行時にPYTHONPATHを頑張って通す人がいますが、setuptoolsでビルドしているので、pyproject.tomlの設定だけで済みます。

name: test-on-merge

on:
  push:
    branches: ["main"]

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  tests:
    runs-on: ubuntu-latest

    steps:
      - name: Check out repository code
        uses: actions/checkout@v4

      - name: Install uv
        uses: astral-sh/setup-uv@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version-file: "pyproject.toml"

      - name: Sync project (create venv + dev deps)
        run: uv sync --dev

      - name: Run tests
        run: uv run pytest

おわりに

と最近少し触って本格移行を考えているuvの使い方説明記事でした!

KGモーターズではアプリ開発、インフラ開発、AI開発を一緒に行う仲間を募集しています!
mibotのソフトウェア開発に興味のある方はお気軽にご連絡ください!

https://kg-m.jp/recruit

KGモーターズ Tech Blog

Discussion