フリーキーズ | 独学プログラミング

超高速なPythonのlinter兼フォーマッターのRuffを導入する

最終更新日
【画像】超高速なPythonのlinter兼フォーマッターのRuffを導入する

「綺麗なコードを書きたい」という気持ちは、すべてのエンジニアの心に宿る願いです。
しかしながら、「納期が…」「まずは動くものを…」という現代社会におけるとめどない流れの中でままならないことも多いでしょう。

そんな悩みを解決する一助となるコードフォーマッター。
今回はPythonのコードフォーマッターの中で、昨今最も注目を浴びているRuffについて紹介します。

Ruffとは

RuffはRust製のPythonコードフォーマッターです。Rust製ですが、Python向けツールとなります。
ここ最近、Rustはその汎用性と高速さを武器に、さまざまなソフトウェアのサポートツールが続々と生まれてきています。そのような流れにおける傑作の1つなのがRuffです。

とにかく速い、という特徴がありますが、その他の特徴も下記に列挙します。

  • Flake8のような)既存linterや(Blackのような)既存フォーマッターより10~100倍高速
  • pipでインストール可能
  • pyproject.tomlサポート
  • 最新安定版のPython 3.12もサポート
  • Flake8isortBlackと共存可能
  • キャッシュ搭載、変更なしのファイルを再検査しない
  • (使われていないimportの削除など)自動エラー修正
  • 700を越える規約ルール含む
  • VSCode等、各種エディタをサポートruff-lspによるもの)
  • モノレポフレンドリー

とにかく全部盛りで、しかも高速というのが売りです。
FastAPI開発者など、Python界隈の名だたるビッグネームがその高速さを称賛しています。

Ruffのインストール

ここまででRuffの魅力は伝わったはずなので早速インストールしましょう。
先述した通り、pipでインストールできます。

pip install ruff
$ ruff --version
ruff 0.1.3

Ruffの簡単なサンプル

動作を確認するために、修正点のあるコードを書いてみましょう。

import datetime as dt

def hello_world():
    print("Hello world!")

もちろんこのコードは正常に動作します。ただ、美しくはありません。
このコードをRuffで修正してみましょう。

ruff check ファイル名でコードの検査ができます。ファイル名.にすることで、カレントディレクトリを起点に検査可能です。

ruff check .

これによって、以下のように出力されます。
使われていないdatetimeモジュールがあることを報告しています。

wrong.py:1:20: F401 [*] `datetime` imported but unused
Found 1 error.
[*] 1 fixable with the `--fix` option.

--fixオプションをつけることで、このコードを自動修正してくれます。

ruff check --fix .

すると、コードから使っていないdatetimeモジュールが取り除かれました。
このように、必要ではないコードが除去されたことでよりクリーンなコードへと生まれ変わるのです。

Ruffの設定

開発チームでコード規約を作る際、共通の設定にしたくなるケースは多々あります。
Ruffpyproject.tomlruff.toml、または.ruff.tomlを親ディレクトリに設置することによってコード規約を設定可能です。

例として、pyproject.tomlをルートディレクトリに作ってみましょう。
以下は一行が長すぎる場合にNGを出すパターンです。(Flake8でデフォルトの79文字)

[tool.ruff]
line-length=79

[tool.ruff.lint]
extend-select = ["E501"]

Ruffで検査、整形

以下のコードを検査してみましょう。

def so_long_list():
    l = ['Apple', 'Banana', 'Chocolate', 'Cookie', 'Peech', 'Orange', 'Cake', 'Pizza', 'Cheeze', 'Beer']
    [print(i) for i in l]
ruff check .

これは下記のような出力をします。

wrong.py:2:5: E741 Ambiguous variable name: `l`
wrong.py:2:80: E501 Line too long (104 > 79)
Found 2 errors.

ついでに曖昧な変数名についても注意されました。一旦、本筋とは違うのでfood_listに修正します。

def so_long_list():
    food_list = ['Apple', 'Banana', 'Chocolate', 'Cookie', 'Peech', 'Orange', 'Cake', 'Pizza', 'Cheeze', 'Beer']
    [print(food) for food in food_list]

これで一行の長さだけ報告されるようになります。
ここで、フォーマッター機能を試しましょう。formatコマンドによって、コードの整形が可能です。

ruff format .

この実行によって、以下のようにコードが整形されます。

def so_long_list():
    food_list = [
        "Apple",
        "Banana",
        "Chocolate",
        "Cookie",
        "Peech",
        "Orange",
        "Cake",
        "Pizza",
        "Cheeze",
        "Beer",
    ]
    [print(food) for food in food_list]

一行の長さを正当にし、配列を読みやすくしてくれました。

Ruffで覚えておくべきコマンド、オプション

Ruffは高速でありつつ、多くの機能が含まれているので主要なコマンドとオプションを覚えておきましょう。

コマンド説明
ruff check [ファイルパス]
コードの分析を行う
ruff rule [ルール名]
コード規約ルールの説明を表示
ruff clean
キャッシュクリア
ruff format [ファイルパス]
コード整形を行う
オプション説明
ruff check --fix修正を適用
ruff check --watch監視モードでリアルタイム検査
ruff check --config [設定ファイルパス]設定ファイルを指定
ruff format --diff整形対象を表示

まずはこのあたりを覚えておくことをおすすめします。
その他のコマンドやオプションを知りたい方はこちらから参照してみてください。

Pythonのコードを高速にチェックしたいならRuff

今回は小さなコードスニペットの検査だけだったので、高速にチェックが終わってしまいましたが、これが大きなプロジェクトになればなるほどRuffの高速さが顕著になっていきます。
すでにBlackFlake8isortを取り入れているプロジェクトでも、Ruffの導入は比較的安全なので、ぜひ検討してみてください。

GitHub Actionsやpre-commitと組み合わせることも多いlinterですが、開発者体験を底上げしてくれる高速なlinter兼フォーマッターのRuffは導入必須な素晴らしいツールです。

pre-commitでPythonプロジェクトをblack/flake8/isort/mypy/banditで管理する

関連するコンテンツ