はじめに #
PythonのフォーマッタblackとisortをRuffに置き換える設定方法を調査しました。 この記事ではリンター機能には触れません。
検証環境は以下の通りです。
- Windows 10 Home 22H2
- Python 3.13.1
- Ruff 0.11.0
- black 25.1.0
- isort 6.0.1
結論 #
Ruffの以下2つのコマンドでblackとisortを代替できます(設定ファイルを使用すると--select I
オプションは省略可能)。
ruff format foo.py
ruff check --fix --select I foo.py
上から順にblack, isortの機能に相当します。foo.py
は対象のスクリプトファイルやフォルダに変更して下さい。
また、上記のコマンドではファイルが変更されます。変更せずに差分をターミナルに表示したい場合、以下のように--diff
オプションを付けます。
ruff format --diff foo.py
ruff check --diff --select I foo.py
以降でRuffの利点、コマンドや設定の詳細を述べます。
Ruffの利点 #
blackやisortはPythonで実装されているのに対して、RuffはRustで実装されています。 そのため、公式サイト にはRuffはblackの10~100倍、高速に動作すると書かれています。
⚡️ 10-100x faster than existing linters (like Flake8) and formatters (like Black)
また、blackやisortをターミナル (PowerShell) で実行したときに文字に色があまり付かないのに対して、Ruffでは色付きで見やすい長所もあります。
blackとisortで変更差分を表示した例:
Ruffで変更差分を表示した例:
Ruffコマンドの詳細 #
blackとisortの機能は、Ruffの異なるサブコマンドで実行されます。
blackによるスクリプト全体のフォーマットの場合、ruff format
サブコマンドとなります。
コマンド | 機能 |
---|---|
ruff format |
コードを修正 |
ruff format --diff |
コードの修正箇所を表示 |
一方、isortによるインポート順のソートは、Ruffのリンター機能に含まれます。
そのため、ruff check
サブコマンドとなります。
コマンド | 機能 |
---|---|
ruff check |
コードの問題点を表示 |
ruff check --diff |
コードの修正箇所を表示 |
ruff check --fix |
コードを修正 |
また、Ruffのデフォルト設定では、isortの機能は無効になっています。
有効にするには、ruff check
サブコマンドに--select I
オプションを付けます。
例を以下に示します。
ruff check --diff --select I foo.py
I
はisortを意味します。
また、Ruffはpyproject.toml
に設定を記述することもできます。その場合は以下のように書きます。
[tool.ruff.lint]
select = ["I"]
ただし、select = ["I"]
とするとisort以外のリンター機能は無効になります。
デフォルトのリンター機能を有効にしたままisortを追加する場合、select = ["E4", "E7", "E9", "F", "B", "I"]
として下さい。
いずれにしても、select
に"I"
を追加した場合、コマンドから--select I
オプションを省略してもisortの機能が有効になります。
Ruffのデフォルト設定 #
次に、blackとisortに関連するRuffのデフォルト設定をpyproject.toml
形式で示します。
black関連 #
Ruffのフォーマットに関するデフォルト設定は、blackのデフォルト設定とほぼ同じです。
[tool.ruff]
# 1行の最大文字数
line-length = 88
# インデント1個あたりの半角スペースの数
indent-width = 4
# Pythonの最小バージョン
target-version = "py39"
# ただし以下のような書き方が推奨される。
# [project]
# requires-python = ">=3.9"
[tool.ruff.format]
# 文字列をダブルクォーテーションで囲む。
# "double" | "single" | "preserve"
quote-style = "double"
# インデントはタブではなく半角スペース
# "space" | "tab"
indent-style = "space"
# falseの場合、改行されたリスト等の要素の末尾にカンマを付ける
skip-magic-trailing-comma = false
# 改行の文字コード。
# "auto" | "lf" | "cr-lf" | "native"
line-ending = "auto"
# docstrings内のPythonコードをフォーマットするか否か。
# Markdown, reStructuredTextのコードブロックやdoctestsをサポートしている。
# 将来のバージョンではデフォルトでtrueになる予定
docstring-code-format = false
# docstrings内のPythonコードをフォーマットするときの1行の長さの設定。
# `docstring-code-format`がtrueの場合のみ有効。
# int | "dynamic"
docstring-code-line-length = "dynamic"
isort関連 #
Ruffのisortに関するデフォルト設定も、isortのデフォルト設定とほぼ同じです。 ただし、isortとblackのデフォルト設定は競合しているため(後述)、black側に統一されています。
Ruffのisortに関する設定は約30個と多いです。 ここでは3つの設定のデフォルト値を示します。
[tool.ruff.lint.isort]
# trueの場合、大文字と小文字を区別する
case-sensitive = false
# trueの場合、アルファベット順ではなく文字数でソート(短い方が先頭)する
length-sort = false
# importセクションの順
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
blackとisortの競合 #
blackとisortのデフォルト設定では、from import
の文が最大長さを超えたときの処理が異なります。
black(およびRuff)のデフォルト設定では、以下のように1要素ずつ改行されます。
from numpy import (
cos,
int8,
int16,
int32,
int64,
sin,
tan,
uint8,
uint16,
uint32,
uint64,
)
isortのデフォルト設定では、最大長さに収まり、かつ行数が少なくなるように改行されます。 ただし、設定でblackと同じスタイルに変更できます。
from numpy import (cos, int8, int16, int32, int64, sin, tan, uint8, uint16,
uint32, uint64)