モダンPython開発環境2026【uv + ruff + ty + pytest ゼロからCI対応まで】
Python開発の現場では、プロジェクトの立ち上げから運用まで、多くの課題に直面します。依存関係の管理、コード品質の維持、正確な型チェック、そして信頼性の高いテスト。これらを効率的にこなすことは容易ではありません。
例えば、新しいPythonプロジェクトを始める場合を想像してください。まず仮想環境を作り、パッケージをインストールします。次にリンターやフォーマッターを設定し、型チェッカーも導入します。そしてテストフレームワークを設定し、CI/CDパイプラインを構築します。この一連の作業は、時間と手間がかかります。
もし、これらの作業が驚くほど高速に、かつ統一された方法で実現できたらどうでしょうか。依存関係の解決に何分も待つ必要はありません。コードの整形やチェックも瞬時に完了します。CIの実行時間も大幅に短縮され、開発サイクル全体が加速します。本記事で紹介するツール群は、まさにそのような未来を実現します。
このツールの組み合わせが最強な理由
今回紹介する uv、ruff、ty、そして pytest の組み合わせは、モダンPython開発環境における最強の布陣と言えます。これらのツールは、それぞれが特定の課題を解決するだけでなく、互いに連携することで驚くべき相乗効果を生み出します。
特に uv、ruff、ty は、いずれもRust言語で開発されたAstral社のプロダクトです。Rustの採用により、これらのツールは既存のPythonツールと比較して桁違いの高速性を実現しています。これにより、開発者は待ち時間を大幅に削減し、より本質的な開発に集中できます。
開発のライフサイクル全体をカバーするこの組み合わせは、以下のようなメリットを提供します。
- 超高速な実行速度: 仮想環境の作成、パッケージのインストール、コードの整形、型チェックなど、あらゆる作業が瞬時に完了します。
- 統一された開発体験: Astral社製のツールは、設計思想が共通しており、シームレスな連携が可能です。
- 高いコード品質と信頼性:
ruffによる厳格なリンティングとフォーマット、tyによる網羅的な型チェック、pytestによる堅牢なテストが、高品質なコードを保証します。 - CI/CDの高速化: ローカルでの実行速度がCI/CDパイプラインにも直結し、フィードバックループが短縮されます。
これらのツールを組み合わせることで、開発効率とコード品質を劇的に向上させ、Python開発の未来を先取りできます。
各ツールの役割と担当領域
このモダンなPython開発環境を構築する上で、各ツールがどのような役割を果たすのかを理解することは重要です。それぞれが特定の領域に特化し、最高のパフォーマンスを発揮します。
uv: 超高速パッケージ&プロジェクトマネージャー
uv は、Rustで書かれた非常に高速なPythonパッケージおよびプロジェクトマネージャーです。従来の pip、pip-tools、pipx、poetry、pyenv、virtualenv などの機能を一つのツールに統合することを目指しています。
- 役割: パッケージのインストール、アンインストール、依存関係の解決、仮想環境の管理、Pythonバージョンの管理など。
- 担当領域: 開発環境のセットアップ、依存関係の管理、プロジェクトの実行。
- 特徴:
pipの10〜100倍高速な実行速度、ユニバーサルなロックファイル、スクリプト実行、グローバルキャッシュによるディスク効率化。
ruff: 爆速リンター&フォーマッター
ruff は、Rustで書かれた極めて高速なPythonリンターおよびコードフォーマッターです。Flake8、isort、Black といった既存のツールの機能を統合し、それらをはるかに凌駕する速度で実行します。
- 役割: Pythonコードのスタイルチェック、潜在的なバグの検出、コードの自動整形。
- 担当領域: コード品質の維持、チーム内でのコードスタイルの統一。
- 特徴: 既存リンターの10〜100倍高速、
pyproject.toml対応、900以上の組み込みルール、自動修正機能、モノレポ対応。
ty: 次世代型チェッカー&言語サーバー
ty は、Rustで書かれた非常に高速なPython型チェッカーおよび言語サーバーです。mypy や Pyright の代替となることを目指し、桁違いの速度と詳細な診断機能を提供します。
- 役割: Pythonコードの型安全性チェック、静的解析によるエラー検出、エディターでのリアルタイムな型情報提供。
- 担当領域: コードの信頼性向上、開発時の早期エラー発見。
- 特徴:
mypyやPyrightの10〜100倍高速、豊富な診断情報、設定可能なルールレベル、部分的に型付けされたコードへの対応、言語サーバー機能(コードナビゲーション、補完など)。
pytest: Pythonの標準的テストフレームワーク
pytest は、Pythonコミュニティで広く利用されているテストフレームワークです。シンプルながらも強力な機能を提供し、小規模なプロジェクトから大規模なエンタープライズアプリケーションまで幅広く活用されています。
- 役割: Pythonコードの単体テスト、結合テスト、機能テストの作成と実行。
- 担当領域: コードの動作保証、リグレッション防止。
- 特徴: 簡潔なテストコード記述、豊富なプラグインエコシステム、フィクスチャによるテストの前処理・後処理の管理、詳細なテストレポート。
実際のワークフロー — コマンド例付きのステップバイステップ
それでは、これらのツールを実際に使って、ゼロからモダンなPython開発環境を構築する手順を見ていきましょう。
1. uvのインストール
uv は、PythonやRustがインストールされていなくても、curl コマンドで簡単にインストールできます。
curl -LsSf https://astral.sh/uv/install.sh | sh
インストール後、uv コマンドが利用できるようになっているか確認します。
uv --version
これで uv の準備は完了です。
2. 新規プロジェクトの作成と初期化
新しいプロジェクトディレクトリを作成し、uv init でプロジェクトを初期化します。uv init は、仮想環境を作成し、pyproject.toml ファイルを生成します。
mkdir my_modern_app
cd my_modern_app
uv init
uv init を実行すると、プロジェクトのルートディレクトリに .venv ディレクトリ(仮想環境)と pyproject.toml ファイルが作成されます。
3. 依存関係の追加
プロジェクトに必要なライブラリを追加します。例えば、Webアプリケーションフレームワークの FastAPI とそのASGIサーバーである uvicorn を追加する場合を考えます。
uv add fastapi uvicorn
これにより、FastAPI と uvicorn が仮想環境にインストールされ、pyproject.toml に依存関係が追記され、uv.lock ファイルが生成されます。uv.lock は、プロジェクトの全ての依存関係とそのバージョンを固定するファイルです。
4. アプリケーションコードの作成
簡単なFastAPIアプリケーションを作成してみましょう。main.py というファイルを作成します。
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"message": "Hello, Modern Python!"}
def greet(name: str) -> str:
return f"Hello, {name}!"
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
このアプリケーションを実行するには、uv run を使います。
uv run uvicorn main:app --reload
ブラウザで http://127.0.0.1:8000 にアクセスすると、「Hello, Modern Python!」というメッセージが表示されます。
5. ruffによるリンティングとフォーマット
ruff を使ってコードの品質をチェックし、整形します。uv は、pyproject.toml で定義されたツールを実行するのに便利です。
まず、ruff を開発依存として追加します。
uv add ruff --dev
次に、ruff でコードをチェックします。
uv run ruff check .
もし整形が必要な箇所があれば、--fix オプションで自動修正できます。
uv run ruff check . --fix
コードのフォーマットも ruff で行います。
uv run ruff format .
これにより、プロジェクト内のPythonファイルが ruff の設定に従って整形されます。
6. tyによる型チェック
ty を使ってコードの型安全性を確認します。
まず、ty を開発依存として追加します。
uv add ty --dev
次に、ty で型チェックを実行します。
uv run ty check .
main.py の greet 関数に型アノテーションがない場合、ty は警告を出す可能性があります。型情報を追加することで、より堅牢なコードになります。
7. pytestによるテスト
pytest を使ってアプリケーションのテストコードを作成し、実行します。
まず、pytest を開発依存として追加します。
uv add pytest --dev
次に、test_main.py というテストファイルを作成します。
# test_main.py
from main import greet
def test_greet_function():
assert greet("World") == "Hello, World!"
assert greet("Python") == "Hello, Python!"
def test_greet_empty_name():
assert greet("") == "Hello, !"
テストを実行します。
uv run pytest
テストが成功すると、結果が表示されます。
設定ファイル・dotfilesの例
各ツールの設定は、pyproject.toml に集約するのがモダンなやり方です。これにより、プロジェクトの設定を一元管理できます。
pyproject.toml
uv init で生成された pyproject.toml を、ruff、ty、pytest の設定で拡張します。
# pyproject.toml
[project]
name = "my_modern_app"
version = "0.1.0"
dependencies = [
"fastapi",
"uvicorn",
]
[project.scripts]
# アプリケーションの実行スクリプトを定義できます
# my-app = "main:app" # 例: uv run my-app で実行可能
[project.optional-dependencies]
dev = [
"ruff",
"ty",
"pytest",
]
[tool.uv]
# uv固有の設定があればここに記述(現時点ではあまり必要ないかも)
[tool.ruff]
# ruffのリンティング設定
# https://docs.astral.sh/ruff/settings/
line-length = 88 # Black互換の行長
target-version = "py312" # ターゲットPythonバージョン
# 有効にするルールセット (Flake8, isort, Black互換など)
# https://docs.astral.sh/ruff/rules/
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"C", # complexity
"I", # isort
"B", # flake8-bugbear
"UP", # pyupgrade
"ANN", # flake8-annotations (一部無効化するかも)
"ASYNC", # flake8-async
"N", # pep8-naming
"D", # pydocstyle (ドキュメンテーション文字列のチェック)
"ISC", # flake8-implicit-str-concat
"TID", # flake8-tidy-imports
"PERF", # perflint
"RUF", # ruff-specific rules
]
ignore = [
"ANN101", # self引数の型アノテーションを無視 (クラスメソッドなどで)
"ANN002", # *args引数の型アノテーションを無視
"ANN003", # **kwargs引数の型アノテーションを無視
"D100", # Missing docstring in public module
"D104", # Missing docstring in public package
]
# 除外するファイルやディレクトリ
exclude = [
".venv",
"__pycache__",
]
[tool.ruff.format]
# ruffのフォーマット設定 (Black互換)
# https://docs.astral.sh/ruff/formatter/
indent-style = "space"
quote-style = "double"
[tool.ty]
# tyの型チェック設定
# https://docs.astral.sh/ty/reference/configuration/
# ターゲットPythonバージョン
target-version = "py312"
# 無視するエラーコードなどを設定できます
# ignore-errors = []
# strict = true # より厳密なチェックを有効にする
# exclude = [
# "tests/",
# ]
[tool.pytest.ini_options]
# pytestの設定
# https://docs.pytest.org/en/latest/reference/customize.html#pyproject-toml
pythonpath = ["."] # プロジェクトルートをPythonパスに追加
addopts = "--strict-markers --strict-config -ra" # 厳格なマーカーと設定、失敗したテストの要約を表示
testpaths = [
"tests", # テストファイルのあるディレクトリ
]
GitHub Actions (CI) の例
GitHub Actionsを使って、プッシュやプルリクエスト時に自動でコード品質チェックとテストを実行するCIパイプラインを構築します。.github/workflows/ci.yml ファイルを作成します。
# .github/workflows/ci.yml
name: Python CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
# uvをPATHに追加
# これはuvのインストールスクリプトが自動で行うが、明示的に追加する例
# echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Set up Python
# uvはPythonバージョン管理もできるが、ここでは一般的なsetup-pythonアクションを使用
uses: actions/setup-python@v5
with:
python-version: '3.12' # 使用するPythonバージョンを指定
cache: 'uv' # uvのキャッシュを利用
- name: Install dependencies with uv
run: uv sync --dev
- name: Run ruff check
run: uv run ruff check .
- name: Run ruff format check
run: uv run ruff format . --check
- name: Run ty check
run: uv run ty check .
- name: Run pytest
run: uv run pytest
このCI設定では、以下のステップを実行します。
- リポジトリをチェックアウトします。
uvをインストールします。- Python 3.12 をセットアップし、
uvのキャッシュを有効にします。 uv sync --devで本番環境と開発環境の依存関係をインストールします。ruff checkでリンティングを実行します。ruff format . --checkでコードが正しくフォーマットされているか確認します。ty checkで型チェックを実行します。pytestでテストを実行します。
これにより、コードがGitHubにプッシュされるたびに、自動的に品質チェックとテストが実行され、問題があれば通知されます。
よくあるトラブルと解決法
新しいツールを導入する際には、いくつかの課題に直面することがあります。ここでは、よくあるトラブルとその解決策を紹介します。
1. uv のインストールがうまくいかない
問題: curl -LsSf https://astral.sh/uv/install.sh | sh を実行しても uv コマンドが見つからない。解決法: インストールスクリプトは通常、~/.cargo/bin に uv を配置し、PATHに追加します。しかし、シェルを再起動しないとPATHが反映されない場合があります。一度ターミナルを閉じ、再度開いてみてください。また、uv がインストールされたディレクトリを明示的にPATHに追加する必要があるかもしれません。
# 例えばbashの場合
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# zshの場合
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
2. uv init で仮想環境が作成されない、またはPythonバージョンが古い
問題: uv init を実行したが、期待通りのPythonバージョンで仮想環境が作成されない、または仮想環境自体が機能しない。解決法: uv はシステムのPATHにあるPythonを利用します。複数のPythonバージョンがインストールされている場合、意図しないバージョンが使われることがあります。特定のPythonバージョンを使いたい場合は、uv init --python python3.12 のように明示的に指定できます。また、uv 自体もPythonバージョン管理機能を持っていますが、現時点では pyenv や asdf といった専用ツールとの併用も検討してください。
3. ruff のルールが厳しすぎる、または緩すぎる
問題: ruff check を実行すると、大量のエラーや警告が表示される。または、もっと厳密にチェックしたい。解決法: pyproject.toml の [tool.ruff] セクションでルールを細かく調整できます。
- ルールを無視する:
ignore = ["E501", "W292"]のように、無視したいルールコードをignoreリストに追加します。 - ルールを追加する:
select = ["ALL"]とすると、全てのルールが有効になります(非常に厳しくなります)。または、特定のプラグイン(例:Dでpydocstyle)を追加できます。 - ファイルやディレクトリを除外する:
exclude = ["old_code/", "data/"]のように、チェック対象から外したいパスを指定します。
4. ty の型エラーが多すぎる
問題: ty check を実行すると、多くの型エラーが表示され、一度に全て修正するのが難しい。解決法: ty は詳細な型チェックを行いますが、既存のプロジェクトに導入する場合、段階的なアプローチが必要です。
- エラーの無視:
pyproject.tomlの[tool.ty]セクションでignore-errors = ["TY001"]のように、特定の型エラーを無視できます。 - 段階的導入: まずは小規模なモジュールから型チェックを導入し、徐々に範囲を広げていくのが効果的です。
--ignore-errorsオプション: コマンドラインで一時的にエラーを無視したい場合はuv run ty check . --ignore-errorsを使用できます。これはCIでは使わず、ローカルでの作業時に利用を検討します。
5. CIでエラーになるがローカルでは問題ない
問題: ローカル環境で uv run ruff check . や uv run pytest が成功するのに、CI(GitHub Actionsなど)で失敗する。解決法:
- ログの詳細確認: CIの実行ログを注意深く確認し、どのステップで、どのようなエラーメッセージが出ているかを特定します。
- 環境の差異: ローカルとCI環境でPythonバージョンやOS、依存パッケージのバージョンが異なっている可能性があります。GitHub Actionsの
setup-pythonアクションで、ローカルと同じPythonバージョンを指定しているか確認してください。また、uv sync --devがCIで正しく実行されているかも確認します。 - キャッシュの問題: CIキャッシュが原因で古い依存関係が使われている可能性も考えられます。一時的にキャッシュを無効にして試すことも有効です。
- CI専用の設定: CI環境でのみ適用される設定(環境変数など)が影響している可能性もあります。
今日からできる実行プラン
このモダンな開発環境を今日から導入するための3つのステップを紹介します。
ステップ1: uvのインストールとプロジェクト初期化
まずは uv をインストールし、新しいプロジェクトを開始するか、既存のプロジェクトに uv を導入します。
uvをインストールします。curl -LsSf https://astral.sh/uv/install.sh | sh- 新しいプロジェクトで
uv initを実行します。mkdir my_new_project cd my_new_project uv init - 既存プロジェクトの場合、
uv init --existingを試すか、手動でpyproject.tomlに[project]セクションを追加し、uv syncで依存関係を同期します。
ステップ2: ruffとtyの導入、pyproject.toml設定
次に、ruff と ty を導入し、pyproject.toml で設定を一元化します。
ruffとtyを開発依存として追加します。uv add ruff ty --devpyproject.tomlに[tool.ruff]と[tool.ty]セクションを追加し、基本的なルールを設定します。 まずは厳しすぎない設定から始め、徐々に調整していくのが良いでしょう。ruffでコードの整形とチェックを試します。uv run ruff format . uv run ruff check .tyで型チェックを試します。uv run ty check .
ステップ3: pytestの導入とCI/CD連携
最後に、pytest を導入してテスト環境を整え、CI/CDパイプラインを構築します。
pytestを開発依存として追加します。uv add pytest --dev- テストコードを作成し、
uv run pytestで実行します。 pyproject.tomlに[tool.pytest.ini_options]セクションを追加し、pytestの設定を記述します。.github/workflows/ci.ymlを作成し、GitHub ActionsにCIパイプラインを構築します。 本記事の例を参考に、uvを使った依存関係のインストール、ruff、ty、pytestの実行ステップを追加します。
これらのステップを踏むことで、あなたのPython開発環境は劇的に進化し、より高速で高品質な開発が可能になるでしょう。
関連ページ
参考文献
- uv GitHub Repository
- uv Documentation
- ruff GitHub Repository
- ruff Documentation
- ty GitHub Repository
- ty Documentation
- pytest Documentation
- GitHub Actions Documentation