Ruff 利用ノート¶
概要¶
公式文書冒頭によると、Ruff は自らを次のように規定している:
An extremely fast Python linter and code formatter, written in Rust.
静的解析や書式整形を超高速に実行するのはありがたい。Ruff はさらに、先行する同種の道具の上を行くと豪語している:
Ruff can be used to replace Flake8 (plus dozens of plugins), Black, isort, pydocstyle, pyupgrade, autoflake, and more, all while executing tens or hundreds of times faster than any individual tool.
Ruff が比較対象に挙げているものを現在利用しているのであれば、乗り換えを検討する価値がある。
See also
インストール・更新・アンインストール¶
複数人で共用するプロジェクトの開発環境に Ruff をインストールする事例では、そのプロジェクトの定める手順に従え。README や pyproject.toml
を読めば判明する。
自分が所有する作業用仮想環境にインストールするならば、愛用している仮想環境ツールがインストールコマンドを実装している場合にはそれを使え。私ならば Miniconda であるから、例えば次のようにする:
conda install -c conda-forge ruff
インストール手順の説明は以上だ。Ruff の更新、アンインストールの手順は、対応する条件におけるインストール手順に合致する手順を選べ。例えば conda を使っているのならば conda uninstall ruff
を走らせる。
See also
構成・カスタマイズ¶
構成ファイルパス¶
Ruff looks for the first
pyproject.toml
,ruff.toml
, or.ruff.toml
file in the file’s directory or any parent directory.
記述の都合上、本稿では構成ファイルとして後者を用いる。これは基本的には対象プロジェクトのルートディレクトリーにだけ置くのがわかりやすい。ディレクトリー階層的に最も近い位置にあるものを ruff は採用するが、そのような構成ファイルが見当たらない場合、使用者固有の構成ファイルを探しに行く。Linux では次のパスが候補となる:
$XDG_CONFIG_HOME/ruff/ruff.toml
構成方式¶
Ruff の機能は Python コードに対する静的解析と書式整形だ。コマンド ruff
check
が静的解析を、ruff format
が書式整形をそれぞれ行う。構成ファイルの区画 [lint]
と区画 [format]
それぞれで機能の挙動を調整可能だ。
区画 [lint]
では select
, ignore
などに対象規則を指定する。
ruff.toml
コード解析オプション指定例¶[lint]
select = ["I",]
ignore = ["PLC0415",]
原子規則は英文字プラス三桁の数字で構成される。E.g.
D203
,F401
.英文字だけを指定することが可能だ。その文字から始まる原子規則すべてを指定することになる。
使わないが、特殊規則
ALL
はすべての規則を意味する。競合規則は Ruff が適宜調停する。
区画 [format]
では書式整形オプションを指定する。二つある引用符をどちらに統一したいのかを明記することなどにも役に立つ。
ruff.toml
書式整形オプション指定例¶[format]
# Enable reformatting of code snippets in docstrings.
docstring-code-format = true
docstring-code-line-length = "dynamic"
# Use 4 space indentation.
indent-style = "space"
# Use `\n` line endings for all files.
line-ending = "lf"
# Enable preview style formatting.
preview = true
# Prefer single quotes over double quotes.
quote-style = "single"
# Ignore the magic trailing comma.
skip-magic-trailing-comma = true
See also
グローバルスコープにはそれ以外の項目を指定する。特にキャッシュ置場を設定しておくのがおすすめだ。ファイルの先頭に配置するのがよい。
ruff.toml
グローバル部分例¶# Use $XDG_CACHE_HOME/ruff
cache-dir = "~/.cache/ruff"
# Allow lines to be as long as 88.
#line-length = 88
# PEP 8 recommends using 4 spaces per indentation level.
indent-width = 4
target-version = "py313"
使用方法・コツ¶
プロジェクトの仮想環境管理ツールに Ruff を組み込むコマンド¶
Ruff 公式文書ではコマンド uv init --lib numbers
を実行してからコマンド uv
add --dev ruff
を実行することで依存関係を追加的に定義する手順を紹介している。実際には、プロジェクトファイル pyproject.toml
に次の構成が追加される:
pyproject.toml
の部分的な例¶[dependency-groups]
dev = [
"ruff>=0.9.1",
]
開発者は仮想環境管理ツールのインストールコマンドを実行して、依存関係として Ruff
をインストールする。または、ツールによっては run
や shell
のようなコマンドがあり、それらの実行時に Ruff を自動的にインストールする。
Ruff コマンドを実行するときも、仮想環境管理ツールの上記のようなコマンドを経由する。
静的解析コマンド¶
コマンド ruff check
で Python コードのマズい箇所を解析、報告させる。使えそうなコマンドラインパターンを記す。
引数なしで Ruff コマンドを実行する場合はプロジェクトにある Python コード全体が解析対象となる。引数にディレクトリーを指定すると、そことそこから下にあるコードすべてが解析対象となる。引数にファイルを直接指定すると、それのみが解析対象となる。
ruff check --show-settings
コード解析構成を TOML 書式で出力する。例えば
linter.rules.enabled
の値を見ると解析対象規則がわかる。ruff check
マズい箇所を含むファイルパス、行数、規則番号を報告する。
ruff check --fix
上記コマンドの報告動作に加え、マズい箇所が機械的かつ安全に修正可能である場合にそれを修正する。
ruff check --statistics
規則違反の総数を表示する。これは便利だ。
ruff check --statistics
実行例¶$ ruff check --statistics 292 F405 [ ] undefined-local-with-import-star-usage 50 F403 [ ] undefined-local-with-import-star 26 E741 [ ] ambiguous-variable-name 17 E402 [ ] module-import-not-at-top-of-file 4 E721 [ ] type-comparison 1 E731 [*] lambda-assignment [*] fixable with `ruff check --fix`
ruff check --unsafe-fixes
その機械的修正が安全でないものも報告させる。
ruff check --fix --unsafe-fixes
上記コマンドの報告動作に加え、安全性を問わず修正対象であるものをすべて修正させる。
ruff check --watch
プロジェクトのファイルすべてを解析し、変更が生じるタイミングで再解析させる。サーバーが走るので、バックグラウンド実行が良い。
ruff check --extend-select RUF100
コードが含む意味のない
noqa
指令を拾う。対象ファイルを変更しない。ruff check --extend-select RUF100 --fix
上記コマンドによる報告に加え、そのような指令に違反するコードをファイルから除去する。
ruff check --select --add-noqa
対象ファイルについて、違反を含む行のすべてに
noqa
指令を追加させる。 Python プロジェクトに Ruff を導入する段階の初動で実行するのが望ましい。
どの規則を自動修正可能であるとみなすかを、コマンドラインまたは構成ファイルから指定することが可能だ。
書式整形コマンド¶
コマンド ruff format
で Python コードの書式を整形する。使えそうなコマンドラインパターンを記す。
ruff format
書式整形を行わせる。引数に関する注意は静的解析コマンドと同じ。以下同様。
ruff format --check
書式整形対象であるファイルを一覧表示させる。対象ファイルを変更させない。
ruff format --diff
書式整形対象であるファイルそれぞれに対して、その内容を変更することなく整形前後の差分を表示させる。端末で作業をしているときに多用したいコマンドだ。
Ruff に特別な処理をさせるコメント集¶
Python コードにコメントとして特定のパターンを記載しておくと、Ruff の挙動が対応するコマンドラインオプション・構成ファイル内容の指示どおりになる。そのようなコメント書式をいくつか挙げる。
Flake8 方式¶
- 行末コメント
# noqa: code
この行が含む規則番号 code の違反を Ruff に見逃すように指示する。公式文書ではこれを Flake8 方式と呼んでいる。
規則を複数指定する場合は番号をカンマで区切って並べればいい。
アクションコメント例¶some_code # noqa: E741, F841
- 行末コメント
# noqa
この行が含む規則違反すべてを Ruff に見逃させる。こんな粗い指示をしてはいけない。
- インポート文塊の最初の行に置く行末コメント
# noqa: I001
インポート文塊に対する整列修正に対する Ruff への抑制指示。
- コメント
# ruff: noqa: code
ファイル全体にわたって規則 code に対する違反をすべて無視する。通常、このコメントだけを記した行をファイルの先頭に挿れる。
- コメント
# ruff: noqa
ファイル全体にわたって違反すべてを無視する。こちらもファイルの先頭に挿れるのが普通だ。
isort 方式¶
次のコメント指令はコードブロックやその他のインライン構成に対して、インポートの並べ替えを選択的に有効または無効にするように指示するものだ。
- インポート文の行末コメント
# isort: skip
,# ruff: isort: skip
当該
import
文を整列対象にさせない。この行を一般コードとして扱わせ、ファイル内import
文区画下に押し下げる。- インポート文塊前にあるコメント行
# isort: skip_file
,# ruff: isort: skip_file
ファイル全体にわたってインポート整列を省略させる。
- インポート文塊前にあるコメント行
# isort: off
,# ruff: isort: off
次の行以降、整列解析を切る。
- インポート文塊前にあるコメント行
# isort: on
,# ruff: isort: on
整列解析が切れていた場合、それを復活させる。
- インポート文塊間にあるコメント行
# isort: split
,# ruff: isort: split
このコメント行の直前までの整列をいったん確定し、直後のインポート文塊を別の塊として途整列させる。
書式整形抑制指令¶
コマンド ruff format
が対象とする整形範囲をコード中からコメントで指示することが可能だ。
- コメント
# fmt: off
および# fmt: on
整形範囲境界を文単位で指示する。
- コメント
# yapf: disable
および# yapf: enable
上とまったく同様。
- コメント
# fmt: skip
直前にある文、デコレーター、関数定義、クラス定義の整形を抑制する。
pre-commit フック¶
Ruff は pre-commit フックを公開している。これにより規則違反のコードをリポジトリーに commit してしまう事故を未然に防止できるだけでなく、生のコードを整形してリポジトリーに更新することも可能だ。
プロジェクトにある YAML ファイル .pre-commit-config.yaml
に当該フックを搭載する GitHub リポジトリー情報およびフック仕様を追記しろ:
.pre-commit-config.yaml
に Ruff フックを組み込む例¶repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.2
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
インポート文の塊を整列する方法¶
ruff check --select I --fix
インポート文の塊を整列する。実行するのはコマンド
ruff format
の直前がよい。
利用者ノート
構成ファイル [lint]
区画に対応番号を含めておけばいい?
VS Code 拡張¶
Visual Studio Code サイドバー EXTENSIONS パネルの検索欄で Ruff と入力すると現れる拡張をインストールし、機能を有効にするとコマンドパレットから関連コマンドを実行することが可能になる。
See also
次のような機能がある:
右クリックメニュー
から解析した規則違反を一覧表示する。コマンドパレットから
コマンドを選択して、CLI でのruff check --fix
相当を実行する。コマンドパレットから
コマンドを選択して、 CLI でのruff format
相当を実行する。
この拡張の機能を完全に引き出すべく、VS Code の settings.json
で関連項目を構成しておく。なお、構成ファイルのパスは Ruff が自動的に検出するものが採用されるとある。
settings.json
例¶{
"[python]": {
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true
},
"ruff.configuration": "/path/to/ruff.toml"
"ruff.format.args": ["--config=/path/to/ruff.toml"]
"ruff.lint.args": ["--config=/path/to/ruff.toml"],
}
Bash 用タブ補完¶
Bash のスタータップファイル .bashrc
の適当な行に次を書け:
# Enable Ruff completion
[ -x "$(command -v ruff)" ] && eval "$(ruff generate-shell-completion bash)"
GitHub Actions¶
自前で Ruff をインストールして ruff check
を実行するワークフローでは出力書式オプション --output-format github
を指定しろ。
あるいは、GitHub に公開済みの astral-sh/ruff-action@v3
を利用することも可能だ。
astral-sh/ruff-action
使用例¶- uses: astral-sh/ruff-action@v3
with:
src: ["./src"]
採用する規則を検討する¶
コマンド ruff rules --all
を実行すれば ruff が支援する規則すべてを出力する。しかし端末画面では読みにくいので Web ブラウザーを使え:
<https://docs.astral.sh/ruff/rules/>
By default, Ruff enables Flake8’s F rules, along with a subset of the E rules, omitting any stylistic rules that overlap with the use of a formatter, like ruff format or Black.
とあるので、まずは F 規則と E 規則を全部流し読みしておく。コードスタイルに関するものは飛ばす感じで。PEP8 に関する N 規則も重要。PERF 規則は効率に関わる。
利用者ノート
構成ファイルやコマンドラインで F 規則を明示的に select
するのは筋が悪いということだ。
上述の default を確認したいならば、コマンド ruff check --show-settings
を走らせて、出力から linter.rules.enabled
および liner.rules.should_fix
を検査すればいい。
Pyflakes (F)¶
F402: ループ変数にインポートした何かと同じ名前を付けてはダメだ。
F{403,405}:
from module import *
はダメだ。F707:
except:
ブロックは書くなら最後に書け。F901:
raise NotImplemented
ではなくraise NotImplementedError
が普通は正しい。
pycodestyle (E, W)¶
Error (E) と Warning (W) の二本立て。
E111: インデントの大きさは設定値の倍数でなければダメ。
E{201..252}: 括弧や句読点と空白文字の入れ方はこのとおりにしないと素人然とする。
E305: 空行が二行ないとダメな場合がある。
E501: 一行の桁数は PEP8 なら 79 桁だが、Ruff では既定 88 桁。
E722: 生の
except:
を書いてはダメだ。W{291..293}: 見えにくい空白文字。
mccabe (C90)¶
isort (I)¶
規則は二つしかなく、インポート文が整列済みであるか、必要なインポートが欠けていないかを調べる。
pep8-naming (N)¶
コーディング規約のうち、識別子の名前に関するものの集合であると考えられる。
簡単な覚え方としては、何らかの名前が should be uppercase である規則がないということだ。
pydocstyle (D)¶
D{100..107}: 公開要素に docstring がないということは論外。
D300: 三重引用符記号は double quotes でなければダメだ。
D404: 主語が this であってはならない。いきなり動詞から始めろ。
pyupgrade (UP)¶
Python 言語バージョンが上がるときに構文などの様式を刷新するために設けられた規則集と考えられる。コードが古ぼけないようにするべく重視したい。
UP004:
class MyClass(object): ...
はもう古い。UP010: Python のアップグレードにより不要になる
from __future__
がそのうち生じる。UP{013,014}:
typing.TypedDict
,typing.NamedTuple
は継承して使う。UP015: 関数
open
呼び出し時の実引数mode="r"
は冗長だそうだ。UP030: 文字列メソッド
format
の中括弧参照において位置番号は明示しない。UP032: そもそも f-string をなるべく使え。
UP038: 複数型チェックのときには
isinstance(x, type1 | type2)
のように縦棒を使って指定する。UP040:
typing.TypeAlias
ではなくキーワードtype
が今や使える。UP045:
typing.Optional
はもはや使わない。
flake8-2020 (YTT)¶
Flake8 系はプラグイン方式を採っていて、プラグインごとに定まった規則集合に対して Ruff が接頭コードを独自に与えて規則をまとめているようだ。
最初の YTT グループは sys.version
および sys.version_info
にまつわる規則集だ。Python 3.13 を使用している現時点ではこれらの規則は不要だろう。
flake8-annotations (ANN)¶
See also
ANN001: 関数定義の引数リストの仮引数それぞれに対して型注釈を与えろ。
ANN{002,003}: 同じく仮引数
*args
,**kwargs
に対しても型注釈を与えろ。ANN{201,202,204..206}: 関数定義の戻り値に対して型注釈を与えろ。
ANN401:
typing.Any
で茶を濁すな。
flake8-async (ASYNC)¶
この規則集は標準モジュール asyncio
だけでなく、サードパーティー製パッケージの使用に対しても検証する。このノートではそういう規則を読むのは省く。
ASYNC100:
await
,async with
,async for
のいずれもないタイムアウト付きコンテキストマネジャーはダメだ。ASYNC109: 非同期タイムアウト関数を自前で実装してはダメだ。具体的には、仮引数
timeout
を有する引数リストの関数定義はダメだ。ASYNC110: 関数
asyncio.sleep
を継続フラグを見続けるwhile
ループ内で呼び出すような構造のコードはダメだ。ASYNC{220,221}: 同期的メソッドを持つサブプロセスやプロセスを非同期関数が作成、実行するのはダメだ。
ASYNC222: 非同期関数定義で同期的関数呼び出しをするのはダメだ。
ASYNC230: 非同期関数定義で
open
のような同期的関数でファイルを開いてはダメだ。ASYNC251: 非同期関数が関数
time.sleep
を呼び出すのはダメだ。
flake8-bandit (S)¶
コードが何らかの危険や脅威から免れていることを保証するための規則集。Python に関係のある規則もあるし、例えばパスワードをハードコードしてはならぬなど、言語の枠組を超えた一般論として設けられた規則もある。
S101: C/C++ 感覚で
assert
を使ってはいけない。まともな例外送出コードに書き換えろ。S102: 組み込み関数
exec
を使うのはダメだ。S108: 一時ファイルを使うにはモジュール
tempfile
を使え。S{110,112}:
except
節で何もしないのはダメで、ログファイルに何か書け。S113:
timeout
引数があれば必ず指定しろ。S201:
debug
引数をハードコードするのはダメだ。S301: 関数
pickle.load
は直接的か間接的を問わず、使うのはダメだ。S303: SHA-256 はとりあえず使っていい。
この辺の番号は専門的な内容が続くので割愛。
S506:
yaml.load
ではなくyaml.safe_load
S{603,604}:
shell=True
は要注意。安全ではない。S607: 実行形式へのパスは絶対パスで指定しなければ安全でない。
S608: SQL 文をハードコードするのはダメだ。
S609:
subprocess.Popen()
の引数にワイルドカードを与えるのはダメだ。S701: Jinja2 使用時に引数
autoescape=True
を与えろ。これは既定値ではない。
flake8-blind-except (BLE)¶
次の例外処理節を使うのはダメだという規則。類似規則が他の節にもある。
裸の
except
except BaseException
except Exception
flake8-boolean-trap (FBT)¶
関数の引数リストに真偽型の仮引数があるのは、コードの呼び出し側から見るとわかりにくい。さらに、この手の関数は動作が高々二通りしかない。関数を将来的に拡張することが困難だろう。代替案として次を検討しろ:
True
,False
の場合それぞれの実装に作り直す。Enum
を採用する。キーワード限定引数に変えて、実引数を与える際に呼び出し元が明示的に意味を示せるようにする。
flake8-bugbear (B)¶
プログラムのバグや設計上の問題を発見するための規則集とのことだ。雑多な項目からなる。
B002: C/C++ における
operator++
,operator--
に相当する演算子はない。B003:
os.environ
を左辺値のように扱うのはダメだ。B005: 文字列の
strip
系メソッドに長さのある文字列を与えるのは誤り。B006: 関数の既定引数に mutable な値を指定するのはダメだ。
B007: 未使用ループ変数は名前を
_
で始めろ。B{009,010}:
getattr
,setattr
よりも直接参照。B011:
raise AssertionError
はpython -O
の影響を受けないのでassert False
より良い。B012:
finally
節でbreak
,continue
,return
文のいずれかを使うと例外が死んでしまう。B017: 例外を送出するためのテストにおいて
BaseException
やException
を試すのはダメだ。もっと特殊な型を試せ。B019: メソッドに対して
@functools.lru_cache
や@functools.cache
を使用するとメモリーリークを生じることがある。B021: docstring に f-string を使うのは誤り。その文字列が対象の
__doc__
となることはない。B022: 趣旨とは外れるが
contextlib.suppress
は知らなんだ。B028: 関数
warnings.warn
を呼ぶときにはstacklevel=2
かそれ以上が推奨。B034: 関数
re.sub
,re.subn
,re.split
にcount
,maxsplit
,flags
を与えるときにはキーワード引数形式でなければダメだ。B901: ジェネレーターで
return
文を書くのはダメだ。StopIteration
を送出したいのであっても、異なる書き方をしろ。B903:
__init__
しかないクラスはダメだ。@dataclass
修飾を使うかcollections.namedtuple
にしろ。B904:
except
節から別の例外を発生させる場合はfrom
を使え。B{905,911}: 関数
zip
,batched
にはキーワード引数strict
と値を明示しろ。
flake8-builtins (A)¶
Python 組み込み型の名前をユーザーコードで変数などに割り当ててしまうのを避けたい。例えば変数に max
という名前を与えていないか、等。
flake8-commas (COM)¶
COM812: コレクションリテラルの CSV の最後の値のケツにもカンマを入れろ。
COM818: 文末のカンマは誤りのはず。ほんとうに
tuple
リテラルを意図しているのならば、丸括弧を明示的に書け。COM819:
tuple
リテラルの CSV の最後の値のケツにはカンマを入れるな。COM812 と整合していないではないか。
flake8-copyright (CPY)¶
これは面白い。コピーライト表記はあるべきだ。
CPY001: Python ファイルの始めの方に Copyright 2025 xxxx のようなクレジット表記をしろ。
flake8-comprehensions (C4)¶
内包記法に関する諸規則。
C{400,401,416}: 冗長な
x for x in y
を書くな。C{403,404}: コンストラクター呼び出しではなく内包表記にしろ。
C{405,406,408,418}: 冗長なコンストラクター呼び出しを書くな。
C413:
reversed(sorted(iterable))
は効率が悪い。C415:
reverse
とsort
を合成するな。C417:
map
を使うな。C419: 冗長なコレクション生成をするな。
C420:
dict.fromkeys(iterable)
の存在を忘れるな。
flake8-datetimez (DTZ)¶
クラス datetime.datetime
に対する安心でない使用を禁止する規則集。特に、タイムゾーン指定 tz
, tzinfo
については必ず指定しろとある。
DTZ001:
datetime
コンストラクターにはtzinfo
を与えろ。DTZ{002,003}: 関数
datetime.today
,datetime.utcnow
はダメ。どちらの代わりにも 関数datetime.now
を使え。DTZ004: 関数
datetime.utcfromtimestamp
ダメ。datetime.fromtimestamp
をtz
指定のうえ使え。DTZ{005,006}: 関数
datetime.now
,datetime.fromtimestamp
はtz
指定必須。DTZ007: 関数
datetime.strptime
を%z
なしで使う場合には次のどちらかの呼び出しを続けろ:.replace(tzinfo=)
.astimezone()
DTZ011: 関数
date.today
はダメ。datetime.now(tz=).date()
としろ。DTZ012: 関数
date.fromtimestamp
はダメ。datetime.fromtimestamp(, tz=).date()
としろ。DTZ901:
datetime.max
,datetime.min
は使うなら.replace(tzinfo=)
で作り直せ。
flake8-debugger (T10)¶
リリースすることになっている Python ファイルにデバッガー起動処理が含まれているのは意図せぬ状況であるはずだ。
T100:
breakpoint
呼び出しを入れたままにするな。
flake8-errmsg (EM)¶
EM101: 例外オブジェクトのコンストラクターに文字列リテラルを渡して
raise
すると(一行で書くと)トレースバックが読みにくくなる。EM102 同じ状況で、f-string リテラルと値指定の組み合わせもダメ。
EM103: 同じ状況で、文字列リテラルとメソッド
format
の組み合わせもダメ。
flake8-executable (EXE)¶
Python ファイルの実行可能パーミッションと shebang が正しく設定されていることを保証する。
EXE001: Shebang を書くのならば
chmod +x
しておかねばならない。EXE002: 逆に、Python ファイルが実行形式ならば shebang がなければならない。
EXE003: Shebang は python のパスを指していなければならない。
EXE005: Shebang はファイルの一行目になければならない。
flake8-future-annotations (FA)¶
from __future__ import annotations
に関係する規則集。
FA{100,102}: 型注釈をする場合にはこのインポート文が実質的に必須。修正挙動は構成要素
target-version
の値が影響する。
flake8-implicit-str-concat (ISC)¶
文字列リテラルの連結に関する規則集。
ISC001: 文字列リテラル同士を空白で連結するのはダメだ。
ISC{002,003}: 複数行にまたがる文字列はバックスラッシュや演算子
+
で連結するのではなく、丸括弧を用いた暗黙的連結法を採れ。
flake8-import-conventions (ICN)¶
定番インポート文をまとめた規則集。
flake8-logging (LOG)¶
LOG001:
Logger
オブジェクトをコンストラクターから生成するのはダメだ。LOG002:
logging.getLogger
には__name__
を渡せ。LOG007:
logging.exception
をexc_info=False
で呼び出したければ、代わりにlogging.error
を呼べ。LOG009:
logging.WARN
ではなくlogging.WARNING
が正しい。LOG015: モジュール
logging
からdebug
,info
, etc. を呼び出すことが可能ではあるが、それをするな。
flake8-logging-format (G)¶
私が今までよく知らなかったログメッセージの書式整形について習得するための規則集。
G001: ログ出力メソッド各種に実引数として渡す文字列で
format
をするのは効率が悪い。代わりに出力メソッドのキーワード引数extra
を上手く指定しろ。G{002..004}: 同じ理由により、いにしえの
%
様式書式整形、文字列を連結すること、f-string を用いることのいずれもダメだ。G010: メソッド名は
warn
ではなくwarning
が正しい。G101: キーワード引数
extra
のキーに次を使うな:name
level
pathname
lineno
msg
args
exc_info
func
sinfo
G201:
logging.error
をexc_info=True
で呼び出したければ、代わりにlogging.exception
を呼べ。G202:
logging.exception
呼び出しではexc_info=True
は不要。
flake8-no-pep420 (INP)¶
__init__.py
を持たない Python ファイルのディレクトリーがあるとする。これらは有効かつインポート可能だが、壊れるツールが存在する。
この手のディレクトリーは名前空間パッケージとして知られる特別なパッケージである場合もあるが、名前空間パッケージはあまり広く使用されていない。したがって、通常のパッケージが __init__.py
を備え忘れたものだと一般的にはみなされる。これを指摘する規則だ。
flake8-pie (PIE)¶
いろいろな規則を寄せ集めたもの。
PIE790: 不要な
pass
や...
は削れ。PIE807: コンストラクター呼び出しで済むような
lambda
式を書くな。
flake8-print (T20)¶
T{201,203}: 関数
print
, 関数pprint.pprint
を呼び出すのはダメだ。
flake8-pyi (PYI)¶
型ヒント用ファイル (.pyi) 向け規則集。私はこのファイルを作らないので割愛。
flake8-pytest-style (PT)¶
Todo
Pytest は重要なパッケージ。ここも当然やる。
flake8-quotes (Q)¶
Q{000,001,002}: 二重引用符が望ましい。構成オプションによる。
Q{003,004}: 文字列リテラル内側に引用符がある場合、外側の引用符と異なっているならばエスケープは不要。
flake8-raise (RSE)¶
RSE102: 引数なしで例外を発生させる場合、
raise
文は例外オブジェクトの他に例外クラスを受け付ける。後者は暗黙的にオブジェクトを生成するので、コンストラクター呼び出し括弧は必要ない。
flake8-return (RET)¶
戻り値に関する規則集だ。
RET501: 戻り値が
None
しかない関数内ではNone
を明示的に返す書き方はダメだ。単にreturn
と書け。RET502:
None
でない値を返すことがある関数ではNone
を暗黙的に返すのはダメだ。return None
と書け。RET503: RET502 と同じ仮定で、関数の最後に
return
を明示しろ。RET504: 代入された変数の
return
を行うまさに直前に、その代入があるのはダメだ。代入文を削って、その右辺と同じものを返せ。RET{505..508}:
return
文やraise
文やcontinue
文やbreak
文を含むif
節にelse
節もあるのはダメだ。
flake8-self (SLF)¶
SLF001: アンダースコアから始まるような名前であるクラスメンバーに外部からアクセスしてはいけない。
flake8-slots (SLOT)¶
余計なメモリーを食わぬように、immutable 型の派生クラス定義では __slots__
の定義を空にしろという規則だ。基底クラスが次のいずれかである場合に適用する:
SLOT000:
str
SLOT001:
tuple
SLOT002:
collections.namedtuple
,typing.NamedTuple
flake8-simplify (SIM)¶
コードを単純なままに保つための規則集。これは重要。
SIM101: 関数
isinstance
は引数に型を複数取れる。SIM102: 入れ子の
if
文を平たく書き直せるならそうしろ。SIM103:
return
文で済むようなif
ブロックを書くな。SIM105:
contextlib.suppress
で済ませたい例外ブロックがないか?SIM107:
finally
節にreturn
文を書いてはいけない。SIM108: 三項演算子や二項演算
or
で済むif
-else
ブロックを書くな。SIM109: オブジェクトが複数対象のいずれかと等しいかどうかを調べるには演算子
in
を使え。SIM110: 組み込み関数
all
,any
のような処理を手で書くな。SIM115: ファイルを開く関数を呼ぶときには
with
文を使え。SIM116: ある種の
if
文連続は辞書オブジェクトアクセスに置き換えろ。SIM117: 入れ子の
with
文はas
節をカンマ区切りで書くことで平たくしろ。SIM118: 辞書メソッド
keys
呼び出しをin
の右側に書くな。SIM210: 値が
True
かFalse
になる三項演算子呼び出しはbool
変換に書き換えろ。SIM211: SIM 210 の裏。オペランドを演算子
not
に作用させろ。SIM212: 三項演算子を
if not
の形で使うな。SIM{222,223}: truthy/falsey な値を複数
or
/and
で連結するな。SIM300:
==
の左辺に定数を置いた条件文は Python でなくてもダサい。SIM401: 辞書メソッド
get
で済む処理をif
で書くな。SIM905: リストリテラルで置き換えられる内容を文字列メソッド
split
の呼び出しで済ますな。SIM910: 辞書メソッド
get
の呼び出しでは第二引数にNone
を書くな。SIM911: 辞書の
keys
とvalues
をzip
するな。それはitems
だ。
flake8-tidy-imports (TID)¶
インポート文は整然としていなければダメだ。
TID252: 相対インポートは兄弟からの相対インポートでなければダメだ。
TID253: インポートが重いモジュールについては、最上位スコープからインポートするのはダメだ。型注釈にしか用いないものをインポートするときには専用
if
文でしろ。
flake8-type-checking (TC)¶
型注釈をする場合、次のような定型コードを書く。この if
ブロックを型検査ブロックと呼ぶことにする。TC は型検査ブロックに関する規則集だ。
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
...
TC{001..003}: 型検査にしか用いない型をインポートする場所が型検査ブロックでないのはダメだ。
TC004: 逆に、実行時機能として用いるものは型検査ブロック外でインポートする必要がある。
TC005: 空の型検査ブロックは不要。
TC006: 関数
typing.cast
呼び出しの第一引数は型そのものではなく、文字列で指定しろ。TC007: 明示的な
TypeAlias
において、実行時に利用できないシンボルへの参照が含まれていてはいけない。これも文字列で指定しろ。TC008: 逆に、文字列ではなく型そのもので別名を与えろ。
TC010:
X | Y
式の型注釈において、型そのものと文字列を混在してはダメだ。
flake8-unused-arguments (ARG)¶
関数定義で未使用の仮引数があるのはダメだ。
ARG{001..004}: サブクラスのメソッド実装などでそのような引数が生じる場合には、変数名の頭に
_
を付けてしのげ。ARG005: ラムダ式でも同様にしろ。
flake8-use-pathlib (PTH)¶
標準モジュール pathlib
の機能で代替可能な旧式コードを置換しろという規則集だ。標準モジュール os
, os.path
のコードが該当しがちだ。
PTH123: 組み込み関数
open
呼び出しをクラスPath
のメソッドopen
になるべく置き換えろ。PTH201:
Path(".")
ではなくPath()
でよい。PTH207: 標準モジュール
glob
の関数glob
,iglob
呼び出しをPath
のメソッドglob
,rglob
で置き換えろ。PTH210: メソッド
with_suffix()
の実引数はドット始まりでなければならない。
flake8-todos (TD)¶
TODO コメント規則集。
TD001:
FIXME
やXXX
ではなくTODO
と書け。TD002:
TODO
に署名をしろ。例えばTODO(someone)
のように。TD003: TODO コメントに関連する URL を書け。
TD004:
TODO
タグは:
で終われ。TD005: TODO コメントに記述がないのではダメだ。
TD006:
TODO
は全文字大文字で書け。TD007:
TODO(someone):
のコロンの次の文字は空白にしろ。
flake8-fixme (FIX)¶
FIX{001..004}:
FIXME
,TODO
,XXX
,HACK
コメントが残っている。問題に対処してからコメントを消せ。
eradicate (ERA)¶
Python ファイルからコメントアウトされたコードを削ることで知られるプログラムの名を冠した規則だ。
pygrep-hooks (PGH)¶
PGH003:
type: ignore
コメントでは何を無視するのかを書け。PGH004:
noqa
コメントには規則番号を付けろ。
Pylint (PL)¶
Pylint はこの分野の老舗だ。違反区分として Convention, Error, Refactor, Warning を設けている。Ruff ではそれぞれに PLC, PLE, PLR, PLW の接頭辞を割り当てている。
PLC{0105,0131}: この記述が理解できぬ場合には PEP483 を熟読しろ。
PLC0206: 辞書を反復するにはメソッド
items()
を明示しろとある。PLC0208: リテラル集合を反復するのはダメだ。
PLC0415:
import
文はよほどのことがない限りスコープの最上位にしか書かない。PLC2801: 二重アンダースコアメソッドを明示的に呼び出すのはダメだ。対応するメソッドを呼べ。
PLE0115:
global
かつnonlocal
である変数はそもそも論理的に矛盾している。PLE0116:
continue
文をfinally
節に書くのは現在はSyntaxError
送出。PLE{0604,0605}:
__all__
の値は文字列からなるlist
またはtuple
とする。PLE1132: キーワード引数で同一キーの実引数を指定するのはダメだ。
PLE1141: なぜ辞書を反復するのにメソッド
items()
を明示するべきなのかの解説がある。キーが特定の型の値である場合にマズイことになる。PLE1700:
async for
文が必要になる場合。PLE4073: 集合オブジェクトの内容を in-place で変更する場合があれば、コピーオブジェクトを反復せざるを得ない。
PLR0124: コード中に
x == x
のようなテストがあれば、それはx
が NaN であるかをテストしていると考えられる。PLR0133: 定数同士を実行時に比較するな。
PLR{0202,0203}: デコレーターとして供給されている関数はデコレーターとして使え。
PLR0904: この規則は邪魔だ。メソッドがたくさんあってもいいではないか。
PLR0917: キーワード限定引数を上手く使いこなせ。関数定義の引数リストの書き方を習得しろ。
PLR1733:
FRUITS.values()
を反復するという解法もある。PLR1736 も同様。PLR2004: これも邪魔だ。この規則のいう common values では間に合っていない。
PLR5501: Python
elif
はよく忘れる。PLR6104: この手の代入演算を augmented assignment と呼ぶのは知らなんだ。
PLR6201:
in [...]
などよりはin {...}
のほうが望ましい。PLW0133: 例外オブジェクトを
raise
なしに構築することはない。PLW0177: NaN 判定は
math.isnan
かnp.isnan
を使え。直接比較をするな。PLW1510: 関数
subprocess.run
にはcheck=True
を与えろ。PLW1514: テキストファイルを
open
するときにはencoding="utf-8"
を(わかっていても)付けろ。PLW1641:
__eq__
を実装するときには__hash__
も実装しろ。PLW3301: 関数
min
やmax
の呼び出しを入れ子にするな。
tryceratops (TRY)¶
A linter to prevent exception handling antipatterns in Python (limited only for those who like dinosaurs). (About, GitHub guilatrova/tryceratops)
TRY002: 超基本だが
Exception
そのものを送出してはいけない。TRY003: 例外文言は自作した例外クラスの中で組み立てられるように設計しろ。
TRY004:
TypeError
とValueError
のどちらにも取れる状況では前者を送出しろ。TRY201: 処理ブロックから再送出する場合には
raise
に引数を付けない。TRY203: 再送出しかしない
except
節は不要。TRY300:
try
節でreturn
文を書きたい場合、そうはせずにelse
節を設けてそこに置け。TRY301:
try
節に内部関数を定義する場合、その戻り値に基づいたraise
文を書くのはダメ。TRY{400,401}: 関数
logging.exception
を上手く使え。要練習。
flynt (FLY)¶
FLY002: f-string で書ける文字列
join
はダメだ。
NumPy-specific rules (NPY)¶
NumPy を使うときにオンにする規則集。
NPY001:
np.int
などの型別名は一部の除外対象を除き使用不可。単にint
などに書き換えろ。NPY002:
np.random
の関数のうち、旧式のものを使用してはダメだ。NPY003: NumPy が deprecated だと認定しているインターフェイスを使用してはいけない。
NPY201: numpy2-deprecation
FastAPI (FAST)¶
FastAPI というサードパーティー製パッケージに関する規則集。知らないので割愛。
Airflow (AIR)¶
Apache Airflow というサードパーティー製パッケージに関する規則集。知らないので割愛。
Perflint (PERF)¶
性能に関する規則集。
PERF101: 例えば
for i in list(iterable): ...
のようなlist
はダメだ。PERF102: 辞書に関して、メソッド
items
よりもkeys
,values
で済む場合はそうしろ。PERF203: ループの中に
try
ブロックを書くな。PERF{401,403}: 内包記法で書け。ループを書くな。
PERF402: リストオブジェクトの複製は
list
コンストラクターかメソッドcopy
を使え。
refurb (FURB)¶
ここは耳が痛い規則が多い。
FURB{101,103}: 組み込み関数
open
からのread
/write
はダサい。クラスpathlib.Path
の機能を使え。FURB110:
x if x else y
はx or y
で十分。やらかしていそうで怖い。FURB132: 組み込み型
set
にはメソッドdiscard
がある。FURB136: ところで Python には minmax 関数がない?
FURB142: 集合演算のメソッド名は思い出しにくい。
FURB145:
a[:]
よりもa.copy()
のほうが望ましいとある。FURB148: Sequence を反復するときにインデックスしか要らない場合には
range(len(x))
を用いるのが望ましい。FURB161: 整数メソッド
bit_count
はいずれ使う可能性がある。FURB163: 特殊な底の対数関数は効率や精度が優れた特別版 (e.g.
log10
) がある。FURB166: {2,8,16} 進数を表す文字列を手動で処理していないか。やらかしている可能性が高い。
FURB167:
re.I
などはre.IGNORECASE
などと書かないようではダメだ。FURB181: メソッド
hexdigest
の使用推奨。確認したら大丈夫だった。FURB188: メソッド
removeprefix
,removesuffix
は使った記憶がない。
pydoclint (DOC)¶
Pydoclint は docstring の記述が関数の実際のインターフェイスや定義と一致しているかどうかを検査する。
DOC{201,202}: 意味のある戻り値がある関数に Returns の記述がないのはダメだ。また、戻り値がない関数に Returns の記述があるのはダメだ。
DOC{402,403}: 関数がジェネレーターならば Yields の記述がないのはダメだ。また、関数がジェネレーターでないのに Yields の記述があるのはダメだ。
DOC{501,502}: 明示的に送出する例外をすべて記述しなければダメだ。また、例外を直接送出しないにもかかわらず、送出する可能性があると記述するのはダメだ。
抽象メソッドはこれらの規則の適用外だ。本体が pass
, ...
, raise
NotImplementedError
, これらに類するもので構成されている関数も適用外だ。
Ruff-specific rules (RUF)¶
RUF{001..003}: 日本語混じりのテキストを扱うときにこの規則が邪魔になるか?
RUF005: Sequence を連結する unpacking の手筋。
RUF007: 関数
itertools.pairwise
は知らなんだ。連続する要素の対を反復する。RUF015:
next(iter(x))
手筋。これを指摘されて Ruff に興味を持ったのだった。RUF017: 入れ子になったリストを quadratic list と呼んでいる。
RUF029: なぜかこれをやらかしがちだ。そういう粗忽者は自分だけではないのか。
RUF031:
tuple
がキーであるようなコレクションの要素アクセス。知らなんだ。RUF032:
Decimal(1.2345)
はダメ。Decimal("1.2345")
のように書け。RUF034: FURB110 と同類の規則。
RUF036: 型ヒントの union では
None
を最後に書け。RUF039: 正規表現関数には必ず生文字列を渡せ。
RUF048: バージョン文字列
__version__
は関数packaging.version.parse
に通じる値でなければならない。RUF055: 単純な文字列操作をするのに正規表現操作を適用するのはダメだ。
資料集¶
- Ruff
公式文書。
- Ruff - Visual Studio Marketplace
EXTENSIONS パネルの検索欄で Ruff と入力すると現れる。
- lint - What is “Linting”?
Stack Overflow 内の質疑応答スレ。
- Action Comments - isort
# isort: directive
系コメント指令の仕様はこれに由来する。- How can I print to standard output what rules are currently enabled given my config?
GitHub リポジトリーより。
これ以外にも規則集の原典が多数ある。