はじめに
2022年頃まで、Pythonの開発でLinterやFormaterを導入する場合、以下のツールを採用することが多く見受けられていました。
ツール | 用途 |
---|---|
Flake8 | Linter |
Pylint | Linter |
isort | Import Sorter |
Black | Formatter |
そんな中、これらのツールに対して一石を投じるようなツールが登場しました。それがRuffです。
本稿は、そんなRuffを導入する際の足がかりとして参考になれば幸いです。
Ruffについて
Rustで書かれた非常に高速なPythonのLinterです。
Ruffの特徴
Ruffの特徴として以下のようなものが挙げられます。
⚡️ 既存のリンターよりも 10 ~ 100 倍高速
🐍 経由でインストール可能pip
🛠️ pyproject.tomlサポート
🤝 Python 3.12 との互換性
📦 組み込みのキャッシュにより、変更されていないファイルの再分析を回避します
🔧 自動エラー修正のサポートを修正 (例: 未使用のインポートを自動的に削除)
📏 700 を超える組み込みルール
⚖️ 組み込みの Flake8 ルールセットとほぼ同等
🔌 flake8-bugbear など、数十の Flake8 プラグインのネイティブ再実装
⌨️ VS Codeなどの ファーストパーティエディターの統合
🌎 モノリポに適しており、階層的およびカスケード構成を備えています
https://docs.astral.sh/ruff/ より抜粋
個人的には、以下の点に魅力を感じました。
- 既存のLinterから置き換えが可能
- 主要なLinterのルールをサポートしており、一部ツールに関しては移行ツールも提供されています
- 既存のLinterよりも高速
- 開発中の待ち時間が減り、開発体験の向上に繋がります
-
PEP621に準拠(pyproject.tomlサポート)
- ツールごとで独自の設定ファイルで管理する必要がなくなり、メンテナンスが容易になります
静的解析ツールのトレンド
Ruffの公式ブログで公開されていた、Pythonの開発で広く利用されているツールのGitHub Star数の推移図が以下になります。
Ruffは破竹の勢いでGitHub Starが増えており、注目度の高さが見てとれます。
※本稿執筆時点で確認したところ、Star数は18,000を超えていました。
セットアップ
ローカル環境やエディタ、CI環境への導入方法は以下の通りです。
ローカル環境
ローカルで実行するにあたり、pre-commitを使って実行させる場合は以下のように設定します。
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.0.292
hooks:
- id: ruff
args: [--config, pyproject.toml]
エディタ(VSCode)
Ruff公式からVSCode向けのExtentionが提供されているので、そちらを利用します。
https://github.com/astral-sh/ruff-vscode
保存時に自動で実行させたい場合は、以下のように設定します。
{
"[python]": {
"editor.codeActionsOnSave": {
"source.fixAll.ruff": true,
"source.organizeImports.ruff": true
}
}
}
他にも柔軟に設定ができるので、上記以外の設定はこちらを参照してください。
CI環境(GitHub Actions)
GitHub Actionsで実行させる場合は、以下のように設定します。
name: Ruff
on: [ push, pull_request ]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: chartboost/ruff-action@v1
with:
src: "./src"
version: 0.0.292
args: --config pyproject.toml
詳細はこちらを参照してください。
パフォーマンス
実行時間を計測するにあたり、以下のような条件で計測しました。
コードボリューム
- Pythonファイル数・・・・・・約1800ファイル
- Pythonファイル合計行数・・・約26万行
設定ファイル
[tool.ruff]
target-version="py39"
select = [
"E",
"F",
"W",
"I",
"Q",
]
line-length = 119
[tool.ruff.flake8-quotes]
inline-quotes = "single"
[tool.ruff.isort]
force-single-line = true
実行結果
参考までに、Ruffへの移行前と移行後の実行時間を比較してみましたが、20〜30倍ほど高速化されていることが分かります。
ツール | 実行時間 | 備考 |
---|---|---|
Flake8 | 26.06s user 0.57s system 96% cpu 27.565 total | Ruff移行前 |
isort | 4.01s user 2.13s system 70% cpu 8.768 total | Ruff移行前 |
Ruff | 1.21s user 0.41s system 106% cpu 1.519 total | Flake8とisortのルールは同等 |
Tips
設定ファイルの統合
Ruffの導入以前はFlake8やisortなどの設定ファイルをそれぞれ管理していましたが、Ruffではpyproject.tomlに統一することができます。
詳細はこちらを参照してください。
Ruff導入前
[settings]
force_single_line=true
[flake8]
ignore =
E501,
F821
max-line-length = 119
per-file-ignores =
./tests/*: E101
Ruff導入後
[tool.ruff]
ignore = [
"E501",
"F821",
]
select = [
"E",
"F",
"W",
"I",
]
line-length = 119
[tool.ruff.isort]
force-single-line = true
[tool.ruff.per-file-ignores]
"./tests/*" = ["E101"]
Flake8のルールをRuffに移行する
Ruff公式が提供してくれているflake8-to-ruffを利用することで、Ruff導入以前に適応していたFlake8の設定をRuffに適応させることができます。
ルールの適応方法
すでに開発が進んでいるプロジェクトであれば、上述した移行ツールなどを利用して、既存のルールをRuffに適応させることが多いと思います。
しかし、新規でプロジェクトを立ち上げる場合は、Ruffのルールを全適応させ、必要に応じて無効化する運用が良いと思います。
Ruffであればルールを増やしたとしてもパフォーマンスに影響が出にくく、かつpyproject.tomlで管理できるため、ルールの管理も容易となります。
さいごに
Ruffはリリースから1年ほどしか経過していませんが、既存のLinterから移行するだけの価値がある、非常に魅力的なツールだと感じました。
また、現在はPythonのFormatterとして有名なBlackをサポートする動きもあり、v0.0.289からアルファリリースとして公開されました。
https://github.com/astral-sh/ruff/discussions/7310
(2023/10/26追記)
v0.1.2からベータ版としてフォーマッタがサポートされました!
公式ブログで紹介されているベンチーマークによると、「Blackより30倍、YAPFよりも100倍高速である」とされています。
Ruffは今後ますます注目されるツールになると思います。
今後の動向から目が離せません。