メインコンテンツへスキップ

【Python】blackとisortをRuffで置き換える

·2144 文字·5 分
目次

はじめに
#

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で変更差分を表示した例:

black-isort-diff
black-isort-diff

Ruffで変更差分を表示した例:

ruff-diff
ruff-diff

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)
Helve
著者
Helve
関西在住、電機メーカ勤務のエンジニア。X(旧Twitter)で新着記事を配信中です

関連記事

Jupyter Bookで作成したサイトにPlotlyのグラフを埋め込む
·1205 文字·3 分
Jupyter Bookで作成したサイトにPlotlyのインタラクティブなグラフを埋め込む方法を解説します。
Pyomoのインデックスを作成するSetクラスとRangeSetクラス
·2207 文字·5 分
Pythonの最適化モデリングツールPyomoで、パラメータや変数、制約式のインデックスを作成できるSetクラスとRangeSetクラスについて詳しくまとめました。
【Python】dataclassの継承と初期値・型ヒント・メソッドのオーバーライド
·2442 文字·5 分
Pythonのdataclassを継承して派生クラスを作る方法、および初期値・型ヒント・メソッドのオーバーライドについて解説します。
【Python】dataclassとPandasのSeries, DataFrameを変換する
·1012 文字·3 分
Pythonのdataclassオブジェクトと、PandasのSeries, DataFrameをそれぞれ変換する方法を備忘録として残します。
Pythonのyield文を使って処理の進捗状況を返す
·973 文字·2 分
Pythonの関数内でfor文を使って重たい処理を回すときに、yield文を使って進捗状況を呼び出し元に返す方法を解説します。
pyproject.tomlからpip installコマンドでPythonのライブラリをインストールする
·1918 文字·4 分
Pythonのパッケージ設定ファイルpyproject.tomlに記載されたPythonのパッケージを、パッケージ管理システムpipでインストールする方法を解説します。