【Python】PEP8に沿ったコードスタイルとlinter(Ruff)の使い方

Python

こんにちは、かつコーチです。

「チームメンバーによってインデントや命名がバラバラで、レビューのたびに指摘が発生する」

そんな悩みを持つ現場は少なくありません。

PythonにはPEP8という公式のコードスタイルガイドがあり、これに沿っているかを自動でチェックするlinter(リンター)というツールがあります。

この記事では、PEP8の主要ルール、高速なlinterであるRuffのインストールと実行方法、そしてblackとの違いを解説します。

読み終える頃には、コードスタイルのチェックをチーム全体で自動化できるようになります。

基本の書き方・実装手順

PEP8の主要ルール

PEP8とは、Python公式が定めているコードスタイルのガイドラインです。

代表的なルールは次の通りです。

項目ルール
インデントスペース4つ(タブは非推奨)
1行の長さ79文字以内が目安(実務では99〜120文字まで許容するチームも多い)
変数・関数名snake_case(例:user_name
クラス名PascalCase(例:UserProfile
定数UPPER_SNAKE_CASE(例:MAX_RETRY
import順標準ライブラリ → サードパーティ → 自作モジュールの順に空行区切り
等号周りの空白x = 1のように前後にスペース1つ

すべてを暗記する必要はありません。

これから紹介するRuffが自動でチェックしてくれるためです。

手順1:Ruffをインストールする

仮想環境を有効化した状態で、pipからインストールします。

pip install ruff
ruff --version
ruff 0.7.4

手順2:PEP8違反のあるコードを用意する

わざとPEP8に反したコードをsample.pyとして用意します。

# sample.py
import os
def calcTotal( price,tax_rate = 0.1 ):
    total=price*(1+tax_rate)
    unused_var = 999
    return total

インデントの乱れ、命名規則の違反、余分な空白、未使用変数など、複数の問題を含んでいます。

手順3:ruff checkでチェックする

ruff check sample.py
sample.py:2:5: N802 Function name `calcTotal` should be lowercase
sample.py:2:14: E201 Whitespace after '('
sample.py:2:29: E201 Whitespace after '='
sample.py:3:10: E225 Missing whitespace around operator
sample.py:4:5: F841 Local variable `unused_var` is assigned to but never used
Found 5 errors.

命名規則の違反(N802)、演算子まわりのスペース不足(E225)、未使用変数(F841)などが、行番号付きで一覧表示されます。

手順4:ruff check –fixで自動修正する

修正可能な項目は、--fixオプションで自動修正できます。

ruff check --fix sample.py
# sample.py(自動修正後)
import os


def calc_total(price, tax_rate=0.1):
    total = price * (1 + tax_rate)
    return total

関数名がsnake_caseに、演算子まわりのスペースも自動で整いました。

ただし、osモジュールが使われていない、というような一部の指摘(未使用import等)は手動で確認・修正が必要な場合もあります。

手順5:設定ファイルでルールをカスタマイズする

プロジェクトのルールをチームで統一するには、pyproject.tomlに設定を書きます。

[tool.ruff]
line-length = 100
target-version = "py312"
[tool.ruff.lint]

select = [“E”, “F”, “N”, “W”] ignore = [“E501”]

line-lengthで1行の許容文字数を、selectでチェックするルールの種類を指定できます。

チームごとの事情に合わせて、少しずつ緩めたり厳しくしたりできるのがRuffの柔軟さです。

よくあるつまずきポイント・エラー対処

blackと役割が違うことを知らず二重に導入して混乱する

筆者がRuffを初めて導入したとき、「blackも入れているのに、Ruffがフォーマットまで警告してくる」と混乱したことがあります。

❌ Before(役割の違いを意識せずに導入)

pip install black ruff
black sample.py
ruff check sample.py

blackはコードのフォーマット(整形)専門のツールです。

一方でRuffは、当初はlint(コードの問題検出)専門でしたが、近年はフォーマット機能(ruff format)も備えるようになりました。

両方を役割の理解なしに併用すると、「どちらの設定を優先すべきか」で迷うことになります。

✅ After(役割を理解した上で統一する)

pip install ruff
ruff format sample.py
ruff check --fix sample.py

現在では、Ruff単体でruff format(フォーマット)とruff check(lint)の両方をカバーできます。

ツール主な役割特徴
blackフォーマット専門実行速度は標準的、設定項目が少なく意見が分かれにくい
Ruff(lint)コードの問題検出Rustで実装されており非常に高速、ルールの種類が豊富
Ruff(format)フォーマットblackとほぼ互換の出力、lintと同一ツールで完結できる

新規プロジェクトであれば、Ruff1本にツールチェーンを統一することで、設定ファイルの管理もシンプルになります。

既存プロジェクトでblackが既に定着している場合は、無理に置き換えず、lintの部分だけRuffを追加する形でも問題ありません。

大量の既存コードに導入して警告の山に圧倒される

すでにコード量が多いプロジェクトにRuffを導入すると、数百件の警告が一度に出てくることがあります。

❌ Before(いきなり全ルールを有効化)

[tool.ruff.lint]
select = ["ALL"]
Found 842 errors.

膨大な件数を前に、対応を諦めてしまうケースをよく見かけます。

✅ After(段階的にルールを増やす)

[tool.ruff.lint]
select = ["E", "F"]  # まずは基本的なエラーだけ

まずはE(PEP8の基本ルール)とF(未使用変数など明確なバグの芽)だけを有効にして、警告がゼロになったら次のルールを追加していきます。

一度にすべてを解決しようとせず、少しずつルールを厳しくしていくのが現実的な進め方です。

まとめ

この記事のポイント

  • PEP8は、インデントや命名規則などPython公式のコードスタイルガイド
  • Ruffはruff checkでlint、ruff formatでフォーマットができる高速なツール
  • --fixオプションで多くの違反は自動修正できる
  • blackはフォーマット専門、Ruffはlint+フォーマットの両方をカバーできる
  • 既存プロジェクトへの導入は、ルールを段階的に増やすのが現実的

次に読むべき記事

  • dataclassでシンプルにクラスを定義する
  • 型ヒント(Type Hints)の書き方入門
  • pytestの基本:テストの書き方入門

タグ: Python, 中級者向け, 設計

タイトルとURLをコピーしました