ruffって何?一言でいうと「超高速オールインワンLint&フォーマッタ」
ruff は、Python のコードをチェックするための「超高速リンター兼フォーマッタ」です。
flake8 や isort、部分的には pylint や pyupgrade など、いろんなツールがやっていたことを「ほぼ全部まとめて一つでやる」イメージのツールです。
しかも、とにかく速いです。
小さなプロジェクトだと「実行したのか分からないくらい一瞬」で終わります。
だからこそ、「保存のたびに ruff を走らせる」「CI で毎回 ruff を回す」が現実的にできます。
ざっくり言うと、
コードスタイルチェック(flake8 的なこと)
未使用 import・未使用変数の検出
import の並び替え(isort 的なこと)
一部の自動修正(black ほどではないが、かなり直せる)
を、ruff 一つでこなせます。
まずは「ダメなコード」をruffに見てもらうイメージ
わざと雑なコードを書く
例として、こんなファイルを用意します。
# sample.py
import os, sys
def add(a,b):
x = 1
return a+b
Pythonこのコードには、典型的な問題がいくつかあります。
未使用の import(os, sys)
未使用の変数 x
スペースやインデントがバラバラ
ruff を実行すると、例えばこんな感じの指摘が出ます(イメージ):
sample.py:3:1: F401 `os` imported but unused
sample.py:3:5: F401 `sys` imported but unused
sample.py:5:3: F841 Local variable `x` is assigned to but never used
sample.py:3:12: E401 multiple imports on one line
sample.py:5:12: E231 missing whitespace after `,`
sample.py:4:1: E302 expected 2 blank lines, found 1
flake8 っぽいコード(F401, E231 など)が並んでいますが、
これを「ruff 一つ」で出してくれます。
さらに、ruff は多くの問題を自動修正できます。
ruff check . --fix
のように --fix を付けると、
未使用 import の削除や、カンマ後のスペース挿入などを自動で直してくれます。
ruffが「ただのflake8互換」じゃないところ
複数ツールの役割をまとめてくれる
ruff の強みは、「いろんなツールのルールセットを取り込んでいる」ことです。
flake8 系のルール(E, F など)
isort 的な import 並び替え(I 系)
pyupgrade 的な「古い書き方を新しい書き方に」するルール
バグっぽいコードを検出するルール(例えば == None を is None に、など)
これらを、設定でオン・オフしながら一つのコマンドでチェックできます。
例えば、import の並び替えも ruff に任せられます。
ruff check . --select I --fix
のようにすると、「import の順番・グルーピング」を isort 的なルールで自動整形してくれます。
「flake8 + isort + いろいろ」をバラバラに入れる代わりに、
「ruff 一つ入れておけばだいたい済む」という世界観です。
とにかく速いから「常に回す」が現実的
ruff は Rust で書かれていて、とにかく高速です。
Python 製のリンターと比べると、体感で「桁が違う」ことも多いです。
この速さのおかげで、
保存のたびに ruff を走らせる
pre-commit フックで毎回 ruff を回す
CI で全ファイルに ruff をかける
といった運用がストレスなくできます。
「遅いから後回し」にならないのが、品質的にはかなり大きいです。
ruffとblackの関係:「役割がかぶるところ」と「分けるところ」
ruffもフォーマットを少しやる、でも「全部」ではない
ruff も --fix でかなりの自動修正をしてくれますが、
black ほど「全面的なフォーマット」はしません。
ruff
未使用 import の削除
未使用変数の削除(安全な範囲)
簡単なスタイル修正(スペース、簡単な改行など)
import 並び替え(isort 的)
black
行の折り返し
クォートの統一
辞書・引数の縦並びなど、見た目全体の整形
というイメージです。
実務では、
black で「見た目」を整える
ruff で「ルール違反・バグの匂い」をチェック&一部修正
という組み合わせがかなり多いです。
「ruff だけでフォーマットも全部やる」運用もありますが、
現時点では「フォーマットは black、lint は ruff」という分担が分かりやすいです。
もう少し実践的な例:ruffで「危ない書き方」を直す
古い書き方を新しい書き方にする(pyupgrade 的なこと)
例えば、こんなコードがあったとします。
# old_style.py
x = 1
if x == None:
print("None")
PythonPython 的には x is None の方が良い書き方です。
ruff のルールセットを有効にしておくと、こういう書き方も指摘してくれます。
old_style.py:3:4: E711 Comparison to `None` should be `is None`
--fix を付けて実行すると、自動でこう直してくれます。
if x is None:
print("None")
Pythonこういう「バグの温床になりやすい書き方」を、
機械的にあぶり出して直してくれるのが、ruff のおいしいところです。
未使用変数をあぶり出す
例えば、こんなコード。
def process(items):
count = 0
for i, item in enumerate(items):
count += 1
return len(items)
Pythonここでは count が実質使われていません。
ruff はこれも指摘してくれます。
F841 Local variable `count` is assigned to but never used
これをきっかけに、
「この変数、本当に必要?」
「ロジックを整理できない?」
と自分に問い直すことができます。
ruff は「ただ怒る」のではなく、
「設計を見直すきっかけ」をくれるツールでもあります。
ruffの設定と「うるささ」の調整
すべてのルールをオンにすると、最初はだいたいうるさい
ruff は、かなり多くのルールセットをサポートしています。
全部オンにすると、警告だらけになります。
現実的には、
最初は基本的なルール(E, F, I など)だけ有効にする
慣れてきたら、徐々に追加のルールをオンにしていく
というステップがオススメです。
設定ファイル(pyproject.toml など)で、
有効にするルールや無視するルールを細かく調整できます。
例えば、行の長さを少し緩めたいなら、こんな感じです。
[tool.ruff]
line-length = 100
特定のルールを無視したい場合も、設定で ignore に追加できます。
「全部守る」より「なぜ無視するかを説明できる」ことが大事
ruff のルールは、どれもそれなりの理由があって存在します。
でも、プロジェクトによっては「このルールは現実的じゃない」ということもあります。
そういうときは、
チームで「このルールは無視しよう」と合意する
設定ファイルに「なぜ無視しているか」をコメントで残す
という形にすると、
「考えたうえで無視している」状態になります。
「うるさいから全部オフ」ではなく、
「どこまで厳しくするかを自分たちで決める」感覚が大事です。
初心者がruffから何を学べるか
「良くない書き方」を機械に教えてもらう
ruff のメッセージは、
そのまま「Python のアンチパターン集」みたいなものです。
未使用の import・変数
危険な比較(== None など)
無駄な条件式
古い構文
こういうものを、ruff が全部拾ってくれます。
最初は「なんでこれダメなんだろう?」と思ったら、
エラーコードで検索してみると、
理由や改善例がたくさん出てきます。
それを繰り返すうちに、
「Python らしい書き方」
「バグを生みにくい書き方」
が、自然と体に染み込んでいきます。
「機械に任せるところ」と「自分で考えるところ」を分ける感覚
ruff や black を使うと、
インデント・空白・import の順番・簡単なアンチパターン検出
→ 機械に任せる
設計・責務の分割・テストの観点・仕様の妥当性
→ 自分で(チームで)考える
という分担がはっきりします。
これは、エンジニアとして長くやっていくうえで、かなり重要な感覚です。
「機械でできることは機械に任せて、
人間にしかできないところに集中する」
ruff は、その「境界線」を分かりやすく引いてくれるツールでもあります。
まとめ(ruffは「速くて賢い、lintの総合格闘家」)
ruff を初心者目線で整理すると、こうなります。
ruff は、flake8 や isort などの役割をまとめて担える、超高速なリンター兼フォーマッタで、未使用 import・変数、スタイル違反、古い書き方などを一気にチェックしてくれる。
多くの問題を --fix で自動修正できるので、「指摘して終わり」ではなく「直すところまで」かなり任せられる。
black と組み合わせると、「見た目の整形は black、ルールチェックと軽い修正は ruff」という分担で、コードの品質と一貫性を高いレベルで保てる。
ruff の警告一つひとつが「Python の良くない書き方のレッスン」になり、何度も触るうちに「lint に怒られない=より良いコード」が自然と書けるようになっていく。
もしあなたが今書いているファイルの一部(10〜30行くらい)を貼ってくれたら、
「ruff がどう指摘しそうか」「それをどう直すと設計・可読性の面でも良くなるか」を、具体的なコードを使って一緒に見ていきましょう。
