uv から始まる Python 開発環境構築
0. はじめに
株式会社ディー・エヌ・エーに入社し,MLOps エンジニアをやっている @a5chin です.
本記事では VS Code の Dev Container 上に uv で Python の開発環境を作成します.
CI/CD が入っていたりと,本記事で解説する内容よりもリッチな設定が以下のリポジトリに置いてあるので,ぜひ使って頂けたらと思います.
PR も大歓迎です!
0.1. 背景
2024/08/20 に Astral 社から以下のブログが発表されました.
Python のランタイム・パッケージングを uv 一つで置き換えることができるという発表でした.
Today, we're announcing a series of features that extend uv beyond a pip alternative, and into an end-to-end solution for managing Python projects, command-line tools, single-file scripts, and even Python itself.
本記事では,以前に紹介した『【Rye + uv + Ruff】Docker で VS Code の Dev Container 上に快適な Python 環境を構築する』の続編で,Python パッケージツールを統一した uv を使って開発環境を整備し直していきます.
0.2. 成果物
成果物としては以前の『【Rye + uv + Ruff】Docker で VS Code の Dev Container 上に快適な Python 環境を構築する』と変わりありません.
図 1: Dev Container 上で開発をすると Ruff による自動フォーマット[1]と pre-commit が走る
0.3. 事前準備
本記事で作成したリポジトリを動かすためには,Docker Desktop と VS Code のダウンロード,VS Code 上で Dev Container のインストールが必要です.
また,以下コマンドでリポジトリを clone すると,今後進めやすくなるので clone することをおすすめします.
git clone https://github.com/a5chin/python-uv
0.3.1. Docker Desktop のダウンロード
上記リンクからお使いの OS に合った Docker Desktop をダウンロードしてください↑
Docker Desktop は Mac や Windows に簡単にインストールできるアプリケーションです.
これにより,コンテナ化アプリケーションやマイクロサービスを構築し共有することができます.
0.3.2. VS Code のダウンロード
上記リンクからお使いの OS に合った VS Code をダウンロードしてください↑
VS Code は Microsoft 社から無償で提供されており,Windows, macOS, および Linux で使用できる,軽量ながら強力なソースコードエディターです.
拡張機能によって,全体的な機能に加えてさらに機能を追加することでより快適に開発することができます.
0.3.3. Dev Container のインストール
VS Code 上で VS Code の拡張機能である,Dev Container をインストールしてください.
VS Code 上で⇧⌘x
と入力すると,サイドに Extensions が開くのでms-vscode-remote.remote-containers
と入力して,出てきた拡張機能をインストールしてください.
Dev Container は Microsoft が開発している VS Code の拡張機能です.
Dev Container を使うことで,VS Code から Docker コンテナを開発環境として使用できます.
1. 結論
Step | Save | commit | GitHub Actions |
---|---|---|---|
Python Formatter (Ruff) | ✅ | ✅ | ✅ |
Python Linter (Ruff) | ⛔ | ✅ | ✅ |
Docker Linter (Hadolint) | ⛔ | ✅ | ✅ |
pytest | ⛔ | ⛔ | ✅ |
docker build | ⛔ | ⛔ | ✅ |
上記対応表の様に,私が設定した Dev Countainer 上で開発をすることによって,Format[1:1], Lint[2], Test[3], Build[4] を自動化しています.
1.1. 実際の操作画面
Python プログラムを保存して,git で commit した時の操作画面です.
高速でとても快適です!
図 2: Dev Container 上で開発をすると Ruff による自動フォーマット[1:2]と pre-commit が走る
2. Docker で開発環境を整える
以下では,主に Docker について解説していきます.
Dev Container は Docker コンテナを開発環境として作成するからです.
2.1. uv を使える様にする
Rust[5] で開発されているため,とても高速に動作します.
以下のフローで任意の Docker コンテナ内で uv を使える様にします.
公式イメージが新しく提供され出したので,Multi-stage Build で簡潔に書けるようなりました!
- uv の disstroless[6] な公式イメージから
- 必要なファイルをコピーする
+ FROM ghcr.io/astral-sh/uv:latest AS uv
FROM mcr.microsoft.com/vscode/devcontainers/base:bookworm
+ COPY /uv /uvx /bin/
2.2. プロジェクトの仮想環境を指定する
今回は Dev Container 上にプロジェクトを作成するため,明示的に /home
下を指定してパッケージをインストールします.
{
"name": "uv",
"build": {
"context": "..",
"dockerfile": "Dockerfile",
},
"containerEnv": {
+ "UV_PROJECT_ENVIRONMENT": "/home/vscode/.venv"
},
}
2.3. 開発環境のライブラリを使える様にする
以下のライブラリを .python-version
で指定した Python と pyproject.toml
, uv.lock
で指定したパッケージを uv sync
コマンド を使ってインストールします.
また,VS Code 上で自動フォーマットをしたり,エラーを表示させるために拡張機能が必要なので別途インストールします.
- pre-commit
- pyright
- pytest
- ruff
{
"name": "uv",
"build": {
"context": "..",
"dockerfile": "Dockerfile",
},
"customizations": {
"vscode": {
"extensions": [
+ "charliermarsh.ruff", // ruff の拡張機能
+ "ms-python.python", // pyright に拡張機能が入っています
]
}
},
"containerEnv": {
"UV_PROJECT_ENVIRONMENT": "/home/vscode/.venv"
},
+ "postCreateCommand": "uv sync --frozen",
}
2.3.1. Ruff の設定
図 3: Lint[2:1] する際のスピード比較
Ruff は,上記 GitHub リポジトリで Astral 社が開発している Python 用の Formatter[1:3], Linter[2:2] です.
Rust[5:1] で書かれているため高速で,なんと Pylint[7] の 200 倍以上のスピードです!
Ruff の設定はruff.toml
ファイルで設定を書くことができ,基本的に公式から流用しています.
しかし,上記ドキュメントには Conflict してしまう設定は ignore することを推奨すると書かれていたので,追記しています.
# Exclude a variety of commonly ignored directories.
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]
# Same as Black.
line-length = 88
indent-width = 4
# Assume Python 3.12
target-version = "py312"
[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
select = ["ALL"]
+ ignore = [
+ "COM812", "COM819",
+ "D100", "D203", "D213", "D300",
+ "E111", "E114", "E117",
+ "ISC001", "ISC002",
+ "Q000", "Q001", "Q002", "Q003",
+ "W191",
+ ]
# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[format]
# Like Black, use double quotes for strings.
quote-style = "double"
# Like Black, indent with spaces, rather than tabs.
indent-style = "space"
# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false
# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"
2.3.2. pre-commit の設定
pre-commit
とは,文字通り git コマンドでコミットする前の行動を指定することができます.
今回は以下を commit 前に走らせるように設定します.
- Docker
- lint(hadolint)
- Python
- format(ruff)
- lint(ruff)
{
"name": "uv",
"build": {
"context": "..",
"dockerfile": "Dockerfile",
},
+ "features": {
+ "ghcr.io/dhoeric/features/hadolint:1": {}
+ },
"customizations": {
"vscode": {
"extensions": [
"charliermarsh.ruff",
"ms-python.python",
]
}
},
"containerEnv": {
"UV_PROJECT_ENVIRONMENT": "/home/vscode/.venv"
},
"postCreateCommand": "uv sync --frozen",
+ "postStartCommand": "uv run pre-commit install",
}
default_stages: [commit]
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
hooks:
- id: ruff
name: Ruff check
description: "Run 'ruff check' for extremely fast Python linting"
args: [--fix]
- id: ruff-format
name: Ruff format
description: "Run 'ruff format' for extremely fast Python formatting"
- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.389
hooks:
- id: pyright
name: Pyright type check
description: "Type Check by Pyright"
- repo: https://github.com/hadolint/hadolint
rev: v2.12.0
hooks:
- id: hadolint
name: Lint Dockerfiles
description: Runs hadolint to lint Dockerfiles
language: system
types: ["dockerfile"]
entry: hadolint
2.3.4. Pyright の設定
Microsoft が開発しているの静的型チェックを行うツールです.
以下に mypy
との比較を示しますが,今回は Dev Container との互換性と速度を考慮して Pyright を採用しました.
pyright | mypy | |
---|---|---|
開発元 | Microsoft | Python |
開発言語 | Python + TypeScript | Python + C |
スター数(2024/12) | 135,000 | 186,000 |
スピード | 早い | |
VS Code との互換性 | 良い | |
対応しているエディタ | 多い | |
対応している Python バージョン | 3.x | 2.x, 3.x |
{
"pythonVersion": "3.12",
"pythonPlatform": "All",
"venv": ".venv",
"include": [],
"exclude": [
"**/__pycache__",
".pytest_cache",
".ruff_cache",
".venv"
],
}
2.3.5. VSCode の設定
保存時に .py
ファイルを自動フォーマット[1:4]するために必要な設定の最小構成を以下に示します.
{
"python.defaultInterpreterPath": "/home/vscode/.venv/bin/python",
"[python]": {
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.tabSize": 4
}
}
2.4. ARG を用いる
ARG
は Dockerfile
内で使用できる変数で,変数の値によって生成するイメージの中身を変えることが可能です.
破壊的な変更を避ける目的で,バージョンを固定します.
+ ARG UV_VERSION=0.5.4
+ ARG DEBIAN_VERSION=bookworm
+ FROM ghcr.io/astral-sh/uv:$UV_VERSION AS uv
+ FROM mcr.microsoft.com/vscode/devcontainers/base:$DEBIAN_VERSION
COPY /uv /uvx /bin/
{
"name": "uv",
"build": {
"context": "..",
"dockerfile": "Dockerfile",
+ "args": {
+ "UV_VERSION": "0.5.4",
+ "DEBIAN_VERSION": "bookworm"
+ }
},
"features": {
"ghcr.io/dhoeric/features/hadolint:1": {}
},
"customizations": {
"vscode": {
"extensions": [
"charliermarsh.ruff",
"ms-python.python",
]
}
},
"containerEnv": {
"UV_PROJECT_ENVIRONMENT": "/home/vscode/.venv"
},
"postCreateCommand": "uv sync --frozen",
"postStartCommand": "uv run pre-commit install",
}
3. おまけ
ブランチ毎に機能を分けていく予定なので,機能を追加次第更新していきます.
3.1. jupyter ブランチ
Jupyter Notebook もフォーマットできるようにしました.
主に Jupyter Notebook を使用する時に切り替えるブランチです.
3.2. rye ブランチ
『【Rye + uv + Ruff】Docker で VS Code の Dev Container 上に快適な Python 環境を構築する』で作成した成果物です.
必要がなくなってしまったので,泣く泣くのアーカイブ用です.
4. まとめ
本記事では,VS Code の Dev Container 上に uv と Ruff を使って爆速で快適な Python 環境を構築する方法について解説しました.
よりリッチな設定が以下のリポジトリにあるので,ぜひ使ってください!(PR も歓迎です)
皆さんが快適な Python ライフを送れることを願います💫
-
潜在的なバグや不適切なコーディングスタイルを検出し,それらを修正することでコードの品質を向上できます. ↩︎ ↩︎ ↩︎
-
コードの機能をテストし,期待通りに動作することを確認することです. ↩︎
-
Docker イメージを構築することを指します.イメージからコンテナを作成することができます. ↩︎
-
性能,メモリ安全性,安全な並行性を目指して設計されたマルチパラダイムのプログラミング言語です.C, C++ 言語に代わるシステムプログラミング言語を目指しています. ↩︎ ↩︎
-
OSに関連するパッケージやツールが含まれていないため,イメージサイズが小さいという特徴があります. ↩︎
-
Python における Linter の一種です. ↩︎
Discussion