• トップ
  • ブログ一覧
  • Pythonのパッケージ管理ツール「uv」を試してみた
  • Pythonのパッケージ管理ツール「uv」を試してみた

    こま(エンジニア)こま(エンジニア)
    2025.06.04

    IT技術

    概要

    Pythonのパッケージ管理ツールuvを使ってみたので、使い心地をざっくり書いてみます。

    記事の要約

    • 趣味プロジェクトのパッケージ管理ツールをuvへ移行させた
    • 使ってみたらとても便利だったので、普段の開発ユースケースでどう運用するのが良さそうか整理したい
    • uvはいいぞ

    環境

    • Python: 3.13.2
    • uv: 0.7.8

    背景もとい前置き

    Pythonは主に趣味で触っていましたが、パッケージ管理で苦戦することが多かったです。
    Dockerを使うとIDEと噛み合わせが悪かったり、いろんなツールを試すと仮想環境とパッケージ管理が複雑になってきて
    メンテナンスが大変になったりと、色々迷走してきました。

    Pythonパッケージをアプリケーションごとに隔離し、パッケージを開発・本番環境でシンプルに扱えるような
    ツールを探し続けているので、最近評判のuvに手を出してみようと思います。

    記事の構成

    最初に公式ドキュメントから、uvの概要や基本的な使い方を押さえておきます。
    全体像が見えてきたら、普段の開発でよくあるユースケースをuvでどう実現するのか整理してみます。

    やりたいことをuvで実現する方法から、uvの使い心地はどんなものか見ていきたいです。

    uvを知る

    特徴

    まずは公式ドキュメントで特徴が紹介されているので、ざっと触ってみて良いと思ったものを並べてみます。

    参考

    • 仮想環境を意識しなくてよい
    • 高速
    • 操作感はnpmに近く扱いやすい

    uvを使うことで、Pythonアプリケーションを取り巻くパッケージ管理をシンプルにしてくれそうです。

    プロジェクト

    基本的なコマンドはユースケースから見ていきますが、最初にuvで頻出するプロジェクトについて軽く触れておきます。

    uvにおけるプロジェクトは、npmのプロジェクトに近い構造を持ちます。
    より具体的には、パッケージ情報とパッケージ本体を管理するディレクトリがプロジェクトを指します。

    プロジェクトのディレクトリ構成のサンプルは以下のようになります。

    1$ tree -aL 1
    2.
    3├── .git
    4├── .gitignore
    5├── .python-version
    6├── .venv
    7├── README.md
    8├── main.py
    9├── pyproject.toml
    10├── src
    11└── uv.lock

    アプリケーションで扱うパッケージの情報は、pyproject.tomlファイルに・パッケージ本体は.venvディレクトリに記録されています。

    参考

    uvを触ってみる

    ここからは、実際に手を動かしながら開発でよくあるユースケースをたどることで、uvの使い心地を見ていきます。

    最初の一歩

    まずはパッケージを管理するプロジェクトをつくります。
    uv init <プロジェクト名>コマンドを実行することで、プロジェクトが作成されます。

    参考

    プロジェクトをつくると、プロジェクト名で指定したディレクトリに以下のファイルがつくられます。

    1$ tree -aL 1
    2.
    3├── .git
    4├── .gitignore
    5├── .python-version
    6├── README.md
    7├── main.py
    8└── pyproject.toml

    pyproject.tomlがパッケージ管理を担うファイルで、ここにインストールしたいパッケージ情報を追記していきます。

    パッケージを追加したい

    パッケージはuv addコマンドで追加することができます。

    参考

    例えばDjangoパッケージを加えると、以下のように動作します。

    1$ uv add django
    2# 中略...
    3Creating virtual environment at: .venv
    4Resolved 5 packages in 21ms
    5Installed 3 packages in 63ms
    6 + asgiref==3.8.1
    7 + django==5.2.1
    8 + sqlparse==0.5.3
    1$ tree -aL 1
    2.
    3├── .git
    4├── .gitignore
    5├── .python-version
    6├── .venv
    7├── README.md
    8├── main.py
    9├── pyproject.toml
    10└── uv.lock

    仮想環境をつくると同時に、パッケージを追加してくれます。
    パッケージ管理に関わるファイルがどのように変わったのか見てみます。

    pyproject.toml

    1[project]
    2name = "sample"
    3version = "0.1.0"
    4description = "Add your description here"
    5readme = "README.md"
    6requires-python = ">=3.13"
    7dependencies = [
    8    "django>=5.2.1",
    9]

    重要なのは、キー dependenciesにパッケージが追加されていることです。
    基本的には最新版を追加してくれます。

    参考

    特定のバージョンを指定したい場合は、uv add "django==5.0.0"のように明示的にバージョンを記述します。

    uv.lock

    pyproject.tomlに記述したパッケージバージョンの制約を満たす、実際にインストールされた
    バージョン情報を記述したファイルです。

    このファイルを共有することで、ほかの開発者・本番環境など異なる場所で同じ環境をつくれるようになります。

    参考

    .venv

    パッケージの本体を保管しています。
    詳細は後述しますが、uvが提供しているコマンドを使うことで、仮想環境を意識することなくパッケージを扱えるようになります。

    参考

    ほかの人のつくったプロジェクトから環境をつくりたい

    前述の通り、環境を共有するための情報はuv.lockに記録されています。
    これをもとにuv syncコマンドを実行することで、ほかの開発者と同じ環境が手に入ります。

    IDEと連携させたい

    ここでは、普段使いしているIDEのPyCharmを題材にします。
    Pythonインタープリターからタイプにuvを指定すれば、あとは自動でよしなに設定してくれました。

    Dockerに始まり、ほかのパッケージ管理ツールと変遷してきましたが、とてもシンプルに設定できてよきでした。
    これなら快適に開発できそうです。

    Pythonアプリケーションを動かしたい

    仮想環境で管理されるパッケージを参照しながらPythonアプリケーションを実行したい場合、
    uv run <コマンド名>から動かすことができます。

    参考

    仮想環境を明示的に起動しなくても良いので、シンプルに運用できそうです。

    スクリプトを実行したい

    uvではCLIコマンドを実行するためのインタフェースも用意されています。

    参考

    しかし、Djangoの開発コマンドなど、ディレクトリを移動してコマンドを実行するのには向いてなさそうでした。
    ですので、CLIコマンドを実行したいときは、Taskなどのタスクランナーに任せるのが良さそうです。

    パッケージを更新したい

    追加するときと同じようにuv addコマンドが使えます。
    バージョン制約を改めて指定することで、制約を満たす最新のパッケージに更新してくれます。

    参考

    本番環境向けDockerコンテナをつくりたい

    最近では、本番環境はクラウドサービスを活用し、Dockerコンテナから配信することが多いです。
    そこで、uvを活用してPythonアプリケーションのDockerコンテナをつくりたいです。

    pythonコマンドを実行するだけのシンプルなDockerfileから、uvで管理されたパッケージをどう連携するのか見ていきます。

    1# ベースとなるビルドステージ
    2FROM python:3.13-slim AS base
    3ENV PYTHONDONTWRITEBYTECODE=1
    4
    5FROM base AS build
    6# 環境変数 UV_PROJECT_ENVIRONMENTがuvを理解するのに重要(後述)
    7ENV UV_PYTHON=python3.13 \
    8 UV_PROJECT_ENVIRONMENT=/app
    9
    10RUN apt-get update
    11# uvを導入
    12COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
    13# パッケージをインストール
    14RUN --mount=type=bind,source=uv.lock,target=uv.lock \
    15    --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
    16    uv sync \
    17    --locked \
    18    --no-dev \
    19    --no-editable
    20
    21# 実行に必要なファイルのみで構成されるビルドステージ
    22FROM base AS runtime
    23RUN apt-get update
    24
    25RUN useradd app
    26
    27# ソースコードとパッケージ本体をコピー
    28ENV PATH=/app/bin:$PATH
    29COPY --from=build --chown=app:app /app /app
    30
    31WORKDIR /app
    32
    33USER app
    34
    35ENTRYPOINT ["python"]

    以降では、ポイントとなる部分を抜粋して見ていきます。

    uv syncコマンド

    最も重要なのはuv syncコマンドです。
    プロジェクトで管理されているpyproject.toml, uv.lockを配置し、本番環境向けのオプションを加えています。
    具体的には、バージョンを完全に固定し、本番環境だけに必要なパッケージに絞ってインストールしています。

    参考

    あとはパッケージ本体を実行環境へ配置し、アプリケーションから参照できるような仕組みを整えたいです。

    環境変数 UVPROJECTENVIRONMENT

    パッケージをインストールできたら、アプリケーションから見えるようにすることで動く環境が手に入りそうです。
    これを実現するには、環境変数UV_PROJECT_ENVIRONMENTが鍵を握っています。

    ドキュメントいわく、役割はPythonの仮想環境の場所を決めることです。
    デフォルト値は.venvで、値を変えることで本番向けプロジェクトを構築することができます。

    参考

    何が起きているかは、実際に出来上がったDockerコンテナを見てみるとわかりやすいです。

    1$ which python
    2/app/bin/python
    3
    4$ ls -l /app/bin/python
    5... /app/bin/python -> /usr/local/bin/python3.13

    まず、Pythonの実行ファイルがシンボリックリンクとなっています。環境変数UV_PROJECT_ENVIRONMENTで指定した/appディレクトリが起点になっています。

    さらに、Pythonのsys.path周りを覗いてみます。

    1>>> import sys
    2>>> sys.prefix
    3'/app'
    4>>> sys.path
    5['', '/usr/local/lib/python313.zip', '/usr/local/lib/python3.13', '/usr/local/lib/python3.13/lib-dynload', '/app/lib/python3.13/site-packages']

    Pythonの実行ファイルをシンボリックリンクとすることで、Python本体が管理するprefix directoryの指す場所(sys.prefixの実行結果)が変わります。

    つまり、prefix directory以下をsys.pathに加えてくれます。
    すると、パッケージを管理しているディレクトリがsys.pathに加わるので、アプリケーションからパッケージが参照できるようになります。

    uvはシンプルながらスマートな解決策によって、本番向けPythonアプリケーション実行環境をつくってくれるようでした。

    参考

    触ってみた感想

    趣味プロジェクトにて、別のパッケージ管理ツールからuvに移行してみましたが、
    npmに近い手触りでとても使いやすかったです。
    uv adduv syncuv runコマンドを覚えておけば、基本的なユースケースは対応できそうなのもうれしいです。シンプルに扱えそうで理想に近い触り心地でした。

    これからPythonアプリケーションをつくるときは、uvの力を借りていきたいです。

    まとめ

    本記事では、uvの概要と簡単な使い方を紹介してきました。
    ここで紹介しきれなかった機能以外にも便利なものがたくさんあるので、ぜひ触ってみてください。

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background