新しい Python 用の Linter/Formatter である Ruff を試す
PythonのLinter/Formatter事情
Pythonに限った話ではないですが、チーム開発において、コードの品質と一貫性を保つために欠かせないものといえば、Linter / Formatterですよね。
しかし、こういった環境設定に関するツールは 一度設定すると見直す機会が少なく、最新のツールや手法から取り残される… なんてことは「あるある」なのではないかと思います。
Python でいうと、よく使っている組みあわせは
-
Flake8 (Linter = スタイル・バグ検出)
-
Black (Formatter = コードの自動整形・一貫性担保)
-
isort (importの並べ替え)
-
mypy (型チェック)
などかと思います。実際、身の回りにはこの組みあわせで動いているプロジェクトが多いです。
2025年の1月にはpoetryがバージョン2になったこともあって、最近環境を見直そうと思うようになりました。
その中で Linter/Formatter も見直すことにしたら、最近は Ruff という高速なツールが伸びているということに気付きました。
Ruff の登場
Ruff はRustで実装された高速なPython用のLinter兼Formatterです。
特に推されているポイントは下記の通りです。
-
Rust製であり 高速であること
-
各種Linter/Formatterツールがオールインワンになっていること(Flake8 + Black + isort)みたいな入れ方をしなくてよい
公式ドキュメントの How does Ruff compare to Mypy, or Pyright, or Pyre? のページに
Ruff is a linter, not a type checker. (中略) It's recommended that you use Ruff in conjunction with a type checker, like Mypy, Pyright, or Pyre, with Ruff providing faster feedback on lint violations and the type checker providing more detailed feedback on type errors.
とあるとおり、mypy のような型チェック機能は内包されていないので別途入れる必要がありますが、Ruffとmypyだけで済みそうなのは魅力的です。あと、速いは正義ですよね。
というわけで、早速既存プロジェクトを置き換えてみます。
実際に移行を試してみる
Python 環境側の設定
とりあえず ruff
をいれます。
poetry で管理している場合は
poetry add --group dev ruff
ですね。(もちろん poetry をつかっていなければ pip install
でOKです。)
ついでにFlake8/Black/isortを消しておきます。
poetry remove pyproject-flake8 isort black
VSCode の設定
続いてVSCode側の設定です。
まずは VSCodeのRuff 拡張をインストールします。
Shift + Cmd(Ctrl) + P
等でコマンドパレットを呼び出し「Open User Settings(JSON)」を選択。元々の設定から editor.defaultFormatter
を変更します
(プロジェクトローカルのみの設定としたい場合はプロジェクトルート内に .vscode/settings.json
を作成)
たとえば、 Black を使っていた場合は
"[python]": { // (中略) "editor.defaultFormatter": "ms-python.black-formatter" },
から
"[python]": { // (中略) "editor.defaultFormatter": "charliermarsh.ruff" },
でOKです。
pyproject.toml の設定
地味に面倒な作業はここです。
[tool.flake8]
や [tool.black]
などで指定している値を [tool.ruff]
として指定し直す必要があります。
たとえば、下記のような簡易的な設定は…
[tool.flake8] max-line-length = 119 max-complexity = 10 select = "C,E,F,W,B" ignore = "E203, W503" [tool.black] line-length = 119
置き換えると下記のようになります。
[tool.ruff] line-length = 119 select = ["C", "E", "F", "W", "B"] ignore = ["E203"]
と、こうみるとそこまで複雑ではないのですが、たとえばこの例でいうと W503
がなくなっていますよね。なぜかというと、Ruffにおいて未実装だから、だったりします。
そういった検証が挟まるので、元々の設定が複雑であればあるほどここは時間が掛かるかもしれません。
ちなみにLint 部分は [tool.ruff.lint]
等で指定することも可能です: 公式ドキュメントのConfiguring Ruff のページ が参考になります。
個人的には isort
の際の空行の入り方が気になるので no-lines-before
の指定を入れています。 (公式ドキュメント: no-lines-before)
[tool.ruff.lint.isort] no-lines-before = ["first-party"]
実際に試す
以上でとりあえずの設定はOKです。VSCode上で簡単に動作確認できると思います。
一応コマンドライン上で試す場合は… (poetryの場合)
Lint
poetry run ruff check
Format
poetry run ruff format
となります。(poetry でない場合は PATH が通っていれば poetry run
を外せばOKです)
速い! となるはずなのでコマンドで試すのがオススメです。
まとめ
今回は Linter/Formatter がオールインワンになっている Ruff の導入手順についてまとめました。
実際試してみると動作はめちゃくちゃ速いですが、個人的には既存構成でもそこまで遅いと感じたことはなかったのでもう少し「待ち」でもいいかなと感じました。
2025/01/24 現在のバージョンは0.9.2ということで、開発も活発なので、 v1
リリースで本格導入かな、という印象です。
こういったツールは冒頭でも述べたとおり見直しの機会がなかなかないかもしれませんが、TypeScript/JavaScript であれば Biome のような新しいツールも出てきていたり、サーベイすると意外と乗り換えたほうがいいかも…と思えてくるので、定期的に情報をキャッチアップしておきたいですね。