コード整形、手動でやってない? - ruff + pre-commitで忘れない仕組みを作る
KEY TAKEAWAYS
この記事でわかること
- フォーマッター・リンターの基本(初心者向け)
- ruffによる3ツール統合(Black + flake8 + isort)
- pre-commitによる自動実行の仕組み(実行忘れゼロ)
あなたはこんなことで困っていませんか?
多くのPython開発者が、コード品質で以下のような悩みを抱えています。
フォーマッターって何?
- 「Blackって名前は聞いたことあるけど...」
- 「インデント、改行、スペース...手動で整えるのめんどくさい」
- 「チームメンバーとコードスタイルがバラバラ」
リンター厳しすぎ問題
- 「flake8入れたら怒られまくって開発進まない」
- 「`E501 line too long`とか、どうでもよくない?」
- 「設定ファイルの書き方が分からない」
実行忘れる問題
- 「Black入れたけど、実行するの忘れる」
- 「フォーマット忘れてPR出したら怒られた」
- 「毎回 `black .` 打つのめんどくさい」
この記事で解決できること
- フォーマッター・リンターの基本を理解(初心者でもOK)
- 現実的なリンター設定(厳しすぎない、段階的に導入)
- 自動実行で忘れない仕組み(pre-commitで完全自動化)
そもそもフォーマッター・リンターって何?
まずは基本から。「フォーマッター」「リンター」「pre-commit」の3つの用語を理解しましょう。
TERM 01
フォーマッター(Formatter)
役割: コードのスタイルを自動整形
- インデント(スペース2個 or 4個)
- 改行位置
- 引用符(シングル or ダブル)
- 行の長さ
TERM 02
リンター(Linter)
役割: コードの問題を検出
- 未使用変数
- import順序
- 潜在的なバグ
- 命名規則違反
TERM 03
pre-commit
役割: git commit前に自動実行
- フォーマッター・リンターを自動実行
- コミット前に問題を修正
- 「実行忘れ」がなくなる
TERM 04
ruff
役割: フォーマット + リント + import整理を統合
- Black + flake8 + isortを1つに統合
- Rustベースで爆速(10-100倍高速)
- 設定ファイル1個(pyproject.toml)
フォーマッターの効果:ビフォー・アフター
フォーマッターを使うと、読みづらいコードが一瞬で整います。
def calculate(x,y,z):
result=x+y+z
return result
def process_data(data,options = {'key' :'value'}):
if data>0:
return data*2
return Nonedef calculate(x, y, z):
result = x + y + z
return result
def process_data(data, options={"key": "value"}):
if data > 0:
return data * 2
return Noneなぜフォーマッターが必要?
- チーム全員のコードスタイルが統一される:誰が書いても同じスタイル
- レビュー負担軽減:「インデント直して」みたいな指摘がなくなる
- 可読性向上:読みやすいコードは保守しやすい
リンターの効果:問題の検出
リンターは、潜在的なバグやコーディング規約違反を自動検出します。
# リンターが検出する問題例 import os import sys import django # ❌ E402: import順序が間違ってる(標準→サードパーティ) def process_data(data): result = data * 2 temp = 100 # ❌ F841: 未使用変数 return result def calculate(x): if x=10: # ❌ E999: 構文エラー(== が正しい) return x * 2
なぜリンターが必要?
- バグの原因を事前に検出:実行前に問題を発見
- コードの品質向上:ベストプラクティスに準拠
- レビュー負担軽減:機械的なチェックはツールに任せる
従来の辛さ:Black + flake8 + isort
従来は、フォーマット・リント・import整理を別々のツールで実行していました。これが面倒で、多くの問題を引き起こしていました。
# 1. 複数ツールのインストール pip install black flake8 isort # 2. 設定ファイルが分散 # .flake8, pyproject.toml, setup.cfg...どこに何を書く? # 3. 実行も別々 black . isort . flake8 . # → 3コマンド打つのめんどくさい # 4. 設定が競合 # Blackとflake8の行長設定が違ってエラー...
| 比較項目 | Black + flake8 + isort | ruff |
|---|---|---|
| ツール数 | 3個 | 1個 |
| インストール | 3回 | 1回 |
| 設定ファイル | 複数(.flake8, pyproject.toml等) | 1個(pyproject.toml) |
| 実行コマンド | 3個 | 1個 |
| 速度(10万行プロジェクト) | Black: 5.2秒 + flake8: 20秒 | 0.5秒(50倍速い) |
| 学習コスト | 高い(3つの設定を学ぶ) | 低い(1つだけ) |
"ツールは少なく、効果は最大に。
開発者の時間は、設定ファイルではなく、価値の創造に使うべき。"
解決策:ruffとは何か
ruffは、Black、flake8、isort、pydocstyle等を1つに統合したオールインワンツールです。Rustで実装されており、従来ツールの10-100倍高速です。
ruffのメリット (Pros)
- オールインワン: Black, flake8, isort, pydocstyle等を統合
- 爆速: 10-100倍高速(Rustベース)
- シンプル: 設定ファイル1個(pyproject.toml)
- VSCode対応: 公式拡張機能あり
ruffのデメリット (Cons)
- 一部ルール未実装: flake8の全プラグインには未対応(99%は対応済み)
- 歴史が浅い: 2022年リリース(Black/flake8ほど枯れていない)
ruff導入手順:10分でできます
ruffの導入は非常に簡単です。以下の4ステップで完了します。
- 01
インストール(1分)
Bash# uvを使う場合(推奨) uv pip install ruff # pipを使う場合 pip install ruff # 確認 ruff --version
uvについては、uv記事を参照してください。
- 02
初回実行(1分)
Bash# フォーマット実行 ruff format . # リント実行 ruff check . # リント+自動修正 ruff check --fix .
まずは設定なしで実行してみましょう。デフォルト設定でも十分使えます。
- 03
設定ファイル作成(3分)
設定のポイント
プロジェクトルートに
pyproject.tomlを作成します。最初は緩めの設定で始めて、慣れたら厳しくするのがおすすめです。- line-length: 行の長さ(100文字推奨)
- select: 有効にするルール
- ignore: 無視するルール(E501は無視が現実的)
ポイント:
E501(行長すぎ)は無視するのが現実的。TOML: pyproject.toml[tool.ruff] # 行の長さ(デフォルト88、Blackと同じ) line-length = 100 # Python バージョン target-version = "py311" [tool.ruff.lint] # 有効にするルール select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort(import整理) "N", # pep8-naming ] # 無視するルール(現実的な設定) ignore = [ "E501", # line too long(100文字までOKにしてるので) ] [tool.ruff.lint.isort] # Django用のimport順序 known-first-party = ["myproject"]
- 04
VSCode設定(3分)
自動フォーマットの設定
.vscode/settings.jsonを作成して、保存時に自動フォーマットを有効化します。- defaultFormatter: ruffを設定
- formatOnSave: 保存時に自動実行
- codeActionsOnSave: リント&import整理も自動化
保存時に自動フォーマット!
JSON: .vscode/settings.json{ "[python]": { "editor.defaultFormatter": "charliermarsh.ruff", "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll": true, "source.organizeImports": true } } }
悩み別の解決策
悩み1解決: フォーマッターの使い方
# ファイル全体をフォーマット ruff format . # 特定ファイルのみ ruff format myfile.py # 確認のみ(変更しない) ruff format --check .
実例: フォーマット前後の変化
def my_function(arg1,arg2,arg3): if arg1>0: return arg1+arg2+arg3 return 0
def my_function(arg1, arg2, arg3): if arg1 > 0: return arg1 + arg2 + arg3 return 0
悩み2解決: リンター設定(プロジェクトにあった設定例)
リンターを後から導入する場合は、いきなり厳しくしすぎると挫折します。最低限でもかなりの効果があるのでプロジェクトにあった厳しさにしましょう。もちろん後から徐々に厳しくしていくこともできます。
厳しさの戦略パターン
段階的導入のポイント
最初から全ルールを有効にすると、エラーの嵐で挫折します。
- パターン1: 基本的なエラーのみ(E, F)
- パターン2: import整理追加(I)
- パターン3: 命名規則追加(N)
# パターン1: 最低限 select = ["E", "F"] # パターン2: import整理追加 select = ["E", "F", "I"] # パターン3: 命名規則追加 select = ["E", "F", "I", "N"]
悩み3解決: pre-commitで自動化
pre-commitを導入すると、git commit時に自動でruffが実行されます。実行忘れがゼロになります。
Step 1: pre-commitインストール
uv pip install pre-commit # or pip install pre-commit
Step 2: 設定ファイル作成
pre-commit設定のポイント
プロジェクトルートに .pre-commit-config.yaml を作成します。2つのフックを登録します。
- ruff-check: リント実行(自動修正あり)
- ruff-format: フォーマット実行
- language: system: ローカルにインストールしたruffを使用
repos: - repo: local hooks: # ruff check(リント) - id: ruff-check name: ruff check entry: ruff check --fix language: system types: [python] pass_filenames: false # ruff format(整形) - id: ruff-format name: ruff format entry: ruff format language: system types: [python] pass_filenames: false
Step 3: pre-commit有効化
pre-commit install
これで完了!以降はgit commitすると自動実行
# コミット前に自動でruffが実行される git add . git commit -m "Add feature" # → ruffが自動実行 → 問題あれば修正 → コミット
開発フロー(pre-commit導入後)
pre-commit導入後の開発フローを図解します。
- 1
コード編集
通常通りPythonコードを編集
- 2
ファイル保存
VSCode設定で自動フォーマット
- 3
ruff formatが自動実行
保存時に自動フォーマット(VSCode設定による)
- 4
git add .
変更をステージング
- 5
git commit
コミット実行(pre-commitが発動)
- 6
ruff check --fixが自動実行
pre-commitフックによる自動リント
- 7
自動修正 or エラー表示
問題があれば修正、または手動修正が必要な場合はエラー表示
- 8
コミット完了
「実行忘れ」が発生しない!
article-sample-srcでの実際の使用例
サンプルリポジトリ(article-sample-src)での実例を紹介します。そのままコピーして使えます。
ディレクトリ構造
article-sample-src/ ├── backend/ │ ├── pyproject.toml # ruff設定 │ ├── .pre-commit-config.yaml # pre-commit設定 │ └── myproject/ └── .vscode/ └── settings.json # VSCode設定
実際のpyproject.toml(全文)
実プロジェクトでの設定
サンプルリポジトリで実際に使っている設定です。そのままコピーして使えます。
- exclude: Djangoマイグレーションファイルなどを除外
- select: E, W, F, I, Nの5つのルールセット
- isort: プロジェクト固有のimport整理設定
[tool.ruff] line-length = 100 target-version = "py311" # 除外ディレクトリ exclude = [ "migrations/", "*.pyi", "__pycache__", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "N", # pep8-naming ] ignore = [ "E501", # line too long ] [tool.ruff.lint.isort] known-first-party = ["myproject"]
実際の.pre-commit-config.yaml(全文)
pre-commit実設定
サンプルリポジトリで使っている設定です。コミット前に自動でruffが実行されます。
- repo: local: ローカルにインストールしたruffを使用
- 2つのフック: check(リント)とformat(整形)
- pass_filenames: false: プロジェクト全体を対象
repos: - repo: local hooks: - id: ruff-check name: ruff check entry: ruff check --fix language: system types: [python] pass_filenames: false - id: ruff-format name: ruff format entry: ruff format language: system types: [python] pass_filenames: false
サンプルリポジトリ
ruff + pre-commitの実際の設定を公開
パフォーマンス比較:ruffの速さ
ruffは、従来ツール(Black、flake8等)と比較して圧倒的に高速です。以下は、10万行のDjangoプロジェクトでの実測データです。
リント速度比較(10万行プロジェクト)
Source: Ruff official benchmarks
フォーマット速度比較(10万行プロジェクト)
Source: Ruff official benchmarks
Speed Improvement
10-100x
従来ツール比
Technology
Rust
実装言語
Column: Pythonフォーマッター戦争の歴史
- 2001年: PEP 8(Pythonコーディング規約)策定 - PEP 8
- 2010年: pep8(後のpycodestyle)登場
- 2013年: autopep8登場(自動整形)
- 2015年: yapf登場(Google製)
- 2018年: Black登場(opinionated formatter) - Black公式
- 2019年: Black大流行(設定不要の思想が受け入れられる)
- 2022年: ruff登場(Rustベース、オールインワン) - Astral社
- 2024年: ruff採用率急上昇(Stack Overflow Survey 2024: Python開発者の84%がリンター使用)
なぜruffが選ばれる? Black(フォーマット)+ flake8(リント)+ isort(import)を1つに統合し、Rustベースで爆速、設定もシンプル。開発者の時間を設定ではなく価値創造に使える。
よくあるトラブル
Pro Tip 1: pre-commitが動かない
# pre-commitのインストール確認 pre-commit --version # hookの再インストール pre-commit uninstall pre-commit install
Pro Tip 2: 特定ファイルを除外
除外設定のポイント
自動生成ファイルや型スタブなど、チェック不要なファイルを除外します。
- migrations/: Djangoマイグレーション
- *.pyi: 型スタブファイル
- __pycache__: キャッシュディレクトリ
[tool.ruff] exclude = [ "migrations/", # Djangoマイグレーション "*.pyi", # 型スタブ "__pycache__", ]
Pro Tip 3: pre-commitスキップ(緊急時のみ)
本当に緊急の場合のみ使用してください。
# たまにはスキップしたい時 git commit --no-verify -m "urgent fix"
Black/flake8からの移行ガイド
既存プロジェクトでBlackやflake8を使っている場合の移行手順です。
パターンA: Blackのみ使用中
# 1. ruffインストール uv pip install ruff # 2. Blackアンインストール pip uninstall black # 3. ruff実行 ruff format .
Blackの設定は、ruffのデフォルトとほぼ互換性があります。
パターンB: Black + flake8使用中
# 1. ruffインストール uv pip install ruff # 2. 既存設定を移行 # .flake8の設定をpyproject.tomlに移す # 3. 動作確認 ruff check . ruff format . # 4. 問題なければアンインストール pip uninstall black flake8 isort
flake8の設定は、ruffのルール番号にほぼ対応しています。
CI/CDでの使用例
GitHub Actionsでruffを実行する例です。pre-commitだけでなく、CI/CDでもチェックすると安心です。
GitHub Actionsの設定
CI/CDでもruffチェックを実行して、コード品質を保証します。pre-commitをスキップされても安心。
- checkout: コードを取得
- uv install: 高速なパッケージマネージャー
- ruff check: リント実行
- ruff format --check: フォーマット確認(変更しない)
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Setup Python
run: |
uv venv
source .venv/bin/activate
uv pip install ruff
- name: Run ruff
run: |
ruff check .
ruff format --check .よくある質問 (FAQ)
pyproject.toml設定(line-length、target-version等)は、ruffでもそのまま使えます。ただし、100%完全互換ではないため、移行時は差分を確認することをおすすめします。
flake8-bugbear、flake8-comprehensions等)は既にruffに組み込まれています。詳細はruff公式ルール一覧を参照してください。
--no-verifyでスキップできるため、CI/CDでもruffチェックを実行することで、確実にコード品質を保証できます。チーム全員に導入を推奨し、CI/CDをセーフティネットとして使うのがベストプラクティスです。
次のステップ
コード品質・自動化の悩みは解決しました。次は、型チェックや依存関係管理に進みましょう。
"自動化できることは、自動化すべきだ。"
開発者の時間は、価値の創造に使うために存在する
参考文献・リンク
- Ruff公式ドキュメント - 公式マニュアル、ルール一覧
- Ruff GitHub - ソースコード、Issues、ベンチマーク
- pre-commit公式サイト - pre-commitの使い方、設定例
- Black公式ドキュメント - Blackの思想、設定
- PEP 8 -- Style Guide for Python Code - Pythonコーディング規約
- Astral(開発元) - ruff、uvを開発するAstral社の公式サイト
- article-sample-src - この記事で紹介した設定の実例


まだコメントはありません。最初のコメントを残しませんか?