- はじめに
- 環境
- Ruff について
- Flake8, autoflake を Ruff へ置き換える際に行ったこと
- Black を Ruff へ置き換える際に行ったこと
- isort を Ruff へ置き換える際に行ったこと
- 実行時間比較
- 最後に
- お知らせ
はじめに
- EdTech Lab の中島です。 英語スピーキングテスト PROGOS の機械学習モデル開発・改善などを担当しています。
- Python プロジェクトで利用していた Linter・Formatter ( Flake8, autoflake, Black, isort ) を Ruff に置き換えることで実行時間を約41%~79%短縮することができました。
- 以下では使用した環境と Ruff の概要について記載し、その後 Flake8, autoflake, Black, isort を Ruff へ置き換える際に行った内容を説明します。
環境
- Python 3.9.10
- Poetry 1.8.3
- Ruff 0.8.2
- 使用していた Linter, Formatter
- Flake8 3.9.2 (静的解析のために使用)
- autoflake 1.7.8 (未使用の import, 変数を削除するために使用)
- Black 24.8.0 (Formatter として使用)
- isort 5.13.2 (import をソートするために使用)
Ruff について
- GitHub には以下のような特徴が挙げられています。
- Rust で書かれた高速な Linter 兼 Formatter です。
- 単一の共通インターフェースの下でより多くの機能を統合しながら、他の代替ツールと比べて桁違いに高速であることを目指しています。
- URL先のように多数のオープンソースプロジェクトで使用されています。
Flake8, autoflake を Ruff へ置き換える際に行ったこと
- Flake8, autoflake と Ruff Linter について
- The Ruff Linter には以下の記載があり、Flake8, autoflake を置き換え可能であることが説明されています。
The Ruff Linter is an extremely fast Python linter designed as a drop-in replacement for Flake8 (plus dozens of plugins), isort, pydocstyle, pyupgrade, autoflake, and more.
- The Ruff Linter には以下の記載があり、Flake8, autoflake を置き換え可能であることが説明されています。
設定ファイル変更内容
- setup.cfg に記載されていた Flake8 の設定を pyproject.toml へ移行しました。
- Ruff は pyproject.toml 以外にも、.ruff.toml, ruff.toml に設定を記述することができます。より詳細な説明は URL 先 をご参照ください。
元の setup.cfg 変更前設定内容
# 元の setup.cfg 変更前設定内容 [flake8] max-line-length = 119 ignore = E121,E123,E126,E133,E226,E241,E242,E704,W503,W504,W505,E127,E266,E402,W605,W391,E701,E731,E203 exclude = ./path/to/exclude/folder/*
pyproject.toml 変更内容
# pyproject.toml [tool.ruff] target-version = "py39" line-length = 119 extend-exclude = ["./path/to/exclude/folder/*"] [tool.ruff.lint] # https://docs.astral.sh/ruff/rules/ select = [ "E", # "E" pycodestyle error "F", # "F" Pyflakes "W", # "W" pycodestyle warning ] ignore = ["E203", "E226", "E241", "E242", "E266", "E402", "W391", "W505", "W605", "E701", "E731"] extend-safe-fixes = ["F841"]
pyproject.toml の設定内容詳細
- section 毎に記載します。
- URL 先は関連する Ruff のドキュメントです。
[tool.ruff]
- target-version
- プロジェクトで使用していた Python 3.9 を指定しています。
- line-length
- 長い行の違反(例: E501)を検出する際や後述する isort や Formatter が行を折り返す際に用いる長さです。プロジェクトで使用していた 119 を指定しています。
- extend-exclude
- exclude に加えてフォーマットやリントから除外するファイルパターンのリストです。プロジェクトで使用していた Flake8 の設定に含まれていたフォルダを指定しています。
[tool.ruff.lint]
- select
- Flake8 が wrap している中から Pyflakes, pycodestyle error, pycodestyle warning を指定しました。( McCabe はプロジェクトで使用していなかったため指定していません。)
- ignore
- setup.cfg の ignore のうち Ruff で実装されているものを指定しました。
- extend-safe-fixes
- Ruff が安全でないとみなしている修正を安全なものとして許可するルールを設定可能です。
- 使用していた autoflake のオプション
--remove-unused-variables
と同様の挙動にするため F841 (unused-variable) を追加しました。
Makefile 変更内容
check1: - @poetry run flake8 ./path/to/check1/target + @poetry run ruff check ./path/to/check1/target check2 - @poetry run autoflake --remove-all-unused-imports --remove-unused-variables --in-place --recursive .path/to/check2/target + @poetry run ruff check --fix .path/to/check2/target
- Ruff Linter は
ruff check
command によって実行することができます。 flake8
をruff check
で置き換えました。autoflake
を利用している箇所をruff check --fix
で置き換えました。
Black を Ruff へ置き換える際に行ったこと
- Black と Ruff Formatter について
- Black compatibility には The formatter is designed to be a drop-in replacement for Black. との記載があり
ruff format
を実行することで Black 相当の format を実行することが可能です。( 詳細ドキュメント ) - Black と Ruff Formatter 間の差異については Known Deviations from Black に記載があります。
- Black compatibility には The formatter is designed to be a drop-in replacement for Black. との記載があり
設定ファイル変更内容
pyproject.toml 変更内容
# pyproject.toml [tool.ruff] target-version = "py39" line-length = 119 extend-exclude = ["./path/to/exclude/folder/*"] [tool.ruff.lint] # https://docs.astral.sh/ruff/rules/ select = [ "E", # "E" pycodestyle error "F", # "F" Pyflakes "W", # "W" pycodestyle warning ] ignore = ["E203", "E226", "E241", "E242", "E266", "E402", "W391", "W505", "W605", "E701", "E731"] + [tool.ruff.format] + quote-style = "double"
pyproject.toml の設定内容詳細
[tool.ruff.format]
- quote-style に Black で利用している "double" を指定しました。
Makefile 変更内容
format-check: - @poetry run black --check --diff --line-length 119 .path/to/format/target + @poetry run ruff format --check --diff .path/to/format/target format: - @poetry run black --line-length 119 .path/to/format/target + @poetry run ruff format .path/to/format/target
Black を利用している箇所を
ruff format
で置き換えました。プロジェクトでは、Known Deviations from Black に記載された内容のうち以下の差分が発生し、 Ruff Formatter に合わせて修正を行いました。
isort を Ruff へ置き換える際に行ったこと
- isort と Ruff について
- How does Ruff's import sorting compare to isort ? には isort で
profile = "black"
が利用されている場合ほぼ同等の動作をするように設計されていること、https://github.com/astral-sh/ruff/issues/1381, https://github.com/astral-sh/ruff/issues/2104 で言及されている isort, Ruff の差分があることが記載されています。
- How does Ruff's import sorting compare to isort ? には isort で
設定ファイル変更内容
- 変更前の isort の設定には Ruff のドキュメントに置き換え可能と記載があった
profile = "black"
を使用していました。pyproject.toml 変更内容
# pyproject.toml [tool.ruff] target-version = "py39" line-length = 119 extend-exclude = ["./path/to/exclude/folder/*"] [tool.ruff.lint] # https://docs.astral.sh/ruff/rules/ select = [ "E", # "E" pycodestyle error "F", # "F" Pyflakes + "I", # "I" isort "W", # "W" pycodestyle warning ] ignore = ["E203", "E226", "E241", "E242", "E266", "E402", "W391", "W505", "W605", "E701", "E731"] extend-safe-fixes = ["F841"] [tool.ruff.format] quote-style = "double"
pyproject.toml の設定内容詳細
[tool.ruff.lint]
- isort を利用するために select へ "I" を追加しました。
Makefile 変更内容
format2 - @poetry run isort .path/to/isort/target + @poetry run ruff check --fix .path/to/isort/target && poetry run ruff format .path/to/isort/target
- ドキュメントの以下の引用箇所のように isort 利用箇所は2つのコマンド
ruff check --fix
とruff format
で置き換える必要があります。Sorting imports Currently, the Ruff formatter does not sort imports. In order to both sort imports and format, call the Ruff linter and then the formatter:
実行時間比較
- time コマンドを使用して実行時間を比較しました。
ツール | 変更前 (秒) | 変更後 (秒) | 短縮率 |
---|---|---|---|
Flake8 → Ruff | 3.14 | 0.69 | 79% |
Black → Ruff | 1.79 | 0.67 | 62% |
autoflake → Ruff | 1.53 | 0.55 | 64% |
isort → Ruff | 1.78 | 1.04 | 41% |
最後に
- 今回は 既存の Formatter, Linter を Ruff に置き換える際に行った内容を記載しました。 Ruff は800以上の lint rule をサポートしているため、適用する rule を増やし、コードの品質を向上させたいと考えています。
お知らせ
- 弊社では URL 先の職種を募集しています。ご応募お待ちしております。