フリーキーズ | 独学プログラミング

pre-commitでPythonプロジェクトをblack/flake8/isort/mypy/banditで管理する

最終更新日
【画像】pre-commitでPythonプロジェクトをblack/flake8/isort/mypy/banditで管理する

日常のワークフローにおいて、コードを綺麗に保つことは重要ながら難しいことです。
「後で直す」と頭の片隅に残しつつ、どうしてもその時間が取れないというシーンは多々あります。

そういったシチュエーションで便利なのがPythonのpre-commitです。今回はpre-commitと、それに付随して使うことで効果的になるblackisortmypy、そしてbanditについて簡単に使い方と効果を紹介していきます。

pre-commitとは

pre-commitはPython製ツールで、pre-commitフックを管理・維持するためのものです。
pre-commitフックは、Gitのようなバージョン管理システムでコミットが行われる前に自動的に実行されるスクリプトです。これらのスクリプトは、コードがコミットされる前に特定の基準を満たしているかチェックするために使われます。

pre-commit がどのように機能し、なぜ有効なのかを簡単に説明します。

pre-commitインストール

pre-commitのインストールはpipconda、あるいはhomebrew(macOSの場合)を使いましょう。

pip install pre-commit

condaの場合は以下です。

conda install -c conda-forge pre-commit

homebrewを使う場合は以下です。

brew install pre-commit

pre-commitが動作する流れ

  1. 設定
    まず、.pre-commit-config.yamlファイルをリポジトリに追加します。このファイルで使用するフックを指定します。
  2. インストール
    フックを定義したら、pre-commit installコマンドでフックをインストールします。これにより、コミット前に指定したスクリプトを実行するようgitのフックが設定されます。
  3. 実行
    変更をコミットしようとすると、.pre-commit-config.yamlファイルで指定したフックが実行されます。いずれかのフックが失敗するとコミットは中断され、指定した条件を満たすコードのみがコミットされるようになります。
  4. 更新
    フックはpre-commit autoupdateコマンドを使って新しいバージョンに更新できます。

pre-commitのメリット

  1. 一貫性
    プロジェクトのすべてのコントリビューターが同じコーディング規約に従うことを保証できます。
  2. 品質
    開発プロセスの早い段階で問題を発見し、バグやスタイルの不一致がメインブランチに反映される可能性を減らします。
  3. 自動化
    一度セットアップすればチェックは自動的に実行されるため、スタイルや些細な問題に対する手作業によるコードレビューの必要性が減ります。
  4. 柔軟性
    pre-commitflake8blackのような一般的なlinterからカスタムスクリプトまで、幅広いフックをサポートしています。
  5. 統合
    一般的なCI/CDツールとシームレスに動作し、ローカルとCI/CDパイプラインの両方で同じチェックが実行されることを保証します。

よく使われるフック

  • black = 一貫したコード書式を保証するコードフォーマッター(整形)
  • flake8 = Pythonコードの文法エラーや論理エラーをチェックするlinter
  • isort = Pythonのインポートを一貫性のある方法でソート
  • mypy = Pythonの静的型チェッカー
  • bandit = セキュリティ脆弱性のスキャン
  • カスタムスクリプト = 独自のスクリプトを書いてフックとして使用可能

black, flake8, isort, mypy, banditと組み合わせる

それでは実際に表題の5つのフックを組み合わせていく実例を紹介します。
今回は各ツールの詳細については割愛します。(別のコンテンツで紹介します)

セットアップ

まず、pre-commitがインストールされていることを確認してください。

pre-commit --version

.pre-commit-config.yamlファイル作成

リポジトリのルートに、以下の内容の.pre-commit-config.yamlファイルを作成します。

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.5.0 # 最新版を指定
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer

-   repo: https://github.com/psf/black
    rev: 23.10.0 # 最新版を指定
    hooks:
    -   id: black
        language_version: python3.11 # Pythonのバージョンを指定

-   repo: https://github.com/pycqa/flake8
    rev: 6.1.0 # 最新版を指定
    hooks:
    -   id: flake8

-   repo: https://github.com/pycqa/isort
    rev: v5.11.2 # 最新版を指定
    hooks:
    -   id: isort

-   repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.6.1 # 最新版を指定
    hooks:
    -   id: mypy

-   repo: https://github.com/PyCQA/bandit
    rev: 1.7.5 # 最新版を指定
    hooks:
    -   id: bandit
        args: ["-r", "."]  # 再帰的に現在のディレクトリをスキャン

Gitフックスクリプトをインストールする

pre-commit install

このコマンドを実行すると以下のようなファイルが作成されます。

pre-commit installed at .git/hooks/pre-commit

動作確認

ここまで設定したら動かしてみましょう。例として、README.mdを作成してコミットします。

$ touch README.md
$ git add README.md
$ git commit -m 'add readme'

この時点で、以下のように.pre-commit-config.yamlに書いた内容がインストールされます。

[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Initializing environment for https://github.com/psf/black.
[INFO] Initializing environment for https://github.com/pycqa/flake8.
[INFO] Initializing environment for https://github.com/pycqa/isort.
[INFO] Initializing environment for https://github.com/pre-commit/mirrors-mypy.
[INFO] Initializing environment for https://github.com/PyCQA/bandit.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
...[中略]...
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
black................................................(no files to check)Skipped
flake8...............................................(no files to check)Skipped
isort................................................(no files to check)Skipped
mypy.................................................(no files to check)Skipped
bandit...............................................(no files to check)Skipped

今回は特にチェック対象となるファイルがなかったため、すべてPassed(成功)かSkipped(スキップ)となります。

pre-commitを参考にどのように修正していくか

  • 1度セットアップすると、変更をコミットしようとするたびにpre-commitフックが実行されます。
  • いずれかのツールが問題を報告した場合、コミットは停止され、フィードバックされます。
  • 報告された問題に対処し、再度変更を追加してコミットする必要があります。

効率的にコードの品質を上げるpre-commitを活用しよう

pre-commitはPythonプロジェクトのコード品質を維持する強力なツールです。
レビューを自動化し、コーディング規約を強制することで、クリーンで一貫性があるコードを作成するのに役立ちます。小さな個人プロジェクトでも、大規模なチーム開発のアプリケーションでも、pre-commitは早い段階で取り入れるべきツールだと断言できます。

blackflake8などの複数のツールとpre-commitを統合することで、一括管理できるため、チェックの忘れ防止にも効果的です。安全性が保証と全体的な開発体験の向上を目指して、ぜひpre-commitの導入を検討してみてください。

関連するコンテンツ