9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PythonAdvent Calendar 2023

Day 3

Pythonプロジェクトにlinter・formatterを導入してコードの品質を向上させる

Last updated at Posted at 2023-12-03

作るもの

既存のPythonプロジェクト(ここではFastAPI)にlinterとformatterを導入します。
チーム開発をしているので、コードの品質向上とプルリク時にレビュアーの負担を下げるのが目的です。

やること

  • linter・formatterツールをプロジェクトに導入
  • コミット前に自動で実行してくれるようにする

使うツール

1. black

PEP8に準拠したコードフォーマッター。
細かい設定をする必要もないので、導入しやすいです。

2. flake8

PythoのLinter(静的解析ツール)で、pycodestyle、pyflakes、mccabeをラッパーしています。

3. isort

import文のフォーマットをしてくれます。
PEP8の規定に基づいて自動で修正してくれますので、こちらも導入します。

4. mypy

コードの型チェックをしてくれます。
ただ、これはプロジェクト次第では別になくても良いかなと思ってます。
そもそもpythonが動的型付け言語で、あまり型について気にせず書けるというが強みでもあると思ってるので。

5. pre-commit

こちらはlinter・formatterではなくて、コミット前に自動で実行してチェックしてくれるようにするためのツールです。

プロジェクトに導入

1. ツールをインストール

「使うツール」に記載したパッケージをpipでインストールしていきます。

pip install black flake8 isort mypy

また、「2.」でやる内容の、pyproject.tomlファイルを使って設定する場合は、flake8だけでは無理なので、
もう一つ必要なパッケージをインストールします。

pip install pyproject-flake8

2. 各種設定

pyproject.toml」ファイルを用意することで、ツール一つ一つファイルを作成する必要がなくなり、一つのファイル内に設定を全てまとめることができます。

pyproject.toml
[tool.black]
line-length=120

[tool.flake8]
max-line-length=120
ignore=""
exclude=".venv/"

[tool.isort]
include_trailing_comma = true
line_length = 120
multi_line_output = 3
use_parentheses = true

[tool.mypy]
install_types = true
non_interactive = true

▪️ black
[ line-length ]...1行あたりの文字数を120にします。
それ以外は既存の仕様を使います。

▪️ flake8
[ max-line-length ]...black同様に1行あたりの文字数を120にしてます。
[ ignore ]...解析に含ませたくないエラーコードを入れることができます。今回は全てのパターンを解析させます。

[ exclude ]...解析に含ませたくないフォルダ・ファイルを設定できますので、「.venv」を入れておきます。

▪️ isort
[ include_trailing_comma ]...複数行のインポート時に末尾にカンマをつけるように設定します
[ line_length ]...black同様に120にします
[ multi_line_output ]...複数行になった時の変換方法を指定します。複数パターンありますが、3番に設定します
[ use_parentheses ]...改行をするときにバックスラッシュではなくカンマを使用するに設定させます

▪️ mypy
[ install_types ]...型情報が欠けているライブラリを使用するときに、mypyが型チェックをできるようにするためにスタブファイルをインストールしても良いようにします。
[ non_interactive ]...install_typesに付随する設定で、スタブファイルをインストールするタイミングでユーザーに確認を求めず自動でインストールしてくれるようにします


3. 問題なく動くかチェック

▪️ black

以下を実行。

black --diff .

スクリーンショット 2023-12-03 15.42.37.png
「--diff」をつけることで、フォーマットする時の差分を出してくれます。
ただし、実際にコードを整形してくれるわけではないので、注意。

自動で整形して欲しい時は、

black .

スクリーンショット 2023-12-03 15.42.53.png
これでコードを整形してくれます。
もし特定のファイルだけにblackを実行させたい場合は、「.」をファイルパスかフォルダパスにすればいけます。

▪️ flake8

以下を実行

pflake8 .

スクリーンショット 2023-12-03 16.34.30.png

エラーがある場合はスクショのように表示されます。
もし全てのファイルで問題なければ、何も表示されません。

▪️ isort

以下を実行

isort .

スクリーンショット 2023-12-03 16.38.07.png

import文を整形してくれました。


もし整形して欲しくない場合は以下のようにします。

isort --check-only .

スクリーンショット 2023-12-03 16.42.01.png

▪️ mypy

以下を実行

mypy --ignore-missing-imports .

スクリーンショット 2023-12-03 16.47.10.png
型チェックをするために追加で必要なパッケージを自動でインストールしています。
また、型エラーがあった箇所と内容が表示されてるので問題なく動いてます。


自動化させる

4つのツールをプロジェクトに導入することができましたが、毎回4つのコマンドを叩くのは面倒です。
また、実行自体忘れる可能性があるので、自動で動くようにします。

Pre-commitを使うことで、commitする前にファイルに設定したコマンドを実行してくれます。
範囲スコープはcommit対象のファイルだけなので、プロジェクト全体に向けて実行されるわけではないので注意

全て問題なければそのままcommitしますが、エラーが起きるとcommitされないので、実行忘れのリスクがなくなります。

1. プロジェクトに導入

pip install pre-commit

2. 設定ファイルの作成

.pre-commit-config.yaml」を作成し、ファイル内に以下を記載。

.pre-commit-config.yaml
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
  - repo: local
    hooks:
      - id: black
        name: code format
        entry: black .
        language: system
        types: [file, python]

      - id: isort
        name: import sort
        entry: isort .
        language: system
        types: [file, python]

      - id: pflake8
        name: code lint
        entry: pflake8 .
        language: system
        types: [file, python]

  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.6.1
    hooks:
      - id: mypy
        args: [--ignore-missing-imports]

black→isort→pflake8→mypyの順番に実行してくれます。

black・isort・pflake8はローカルに入れてるパッケージを使って実行させますが、mypyはmirrors-mypyを使って実行させます。(ローカルのだと上手くいかなかったため)


3. Git Hooksスクリプトをインストール

pre-commit install

4. 問題なく動くかチェック

試しにimport文をぐちゃぐちゃにしてcommitしてみました。
スクリーンショット 2023-12-03 17.06.43.png
「import sort」がFailedになって、commitが通りませんでした。


綺麗に直して再度実行してみると、
スクリーンショット 2023-12-03 17.03.21.png
全て通ってcommitできました。


9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?