Pythonで静的解析をしよう

このハンズオンでは、Pythonの静的解析ツールについて実際にハンズオン形式で手を動かしながら体験します。

  • 静的解析とは何か、なぜ重要なのか
  • Flake8を使ったコードスタイルチェック
  • Blackを使ったコード自動フォーマット
  • mypyを使った型チェック
  • VS Codeとの連携

1. 事前準備

このハンズオンでは、以下のツールが必要です。まだ準備できていない場合は、リンク先の手順に沿って準備をお願いします。

2. 静的解析とは

このハンズオンで使用する3つの静的解析ツールの役割を以下に示します。

flowchart LR
    Code[Pythonコード] --> Flake8[Flake8<br>スタイルチェック]
    Code --> Black[Black<br>自動フォーマット]
    Code --> mypy[mypy<br>型チェック]
    Flake8 --> Result1[問題を検出]
    Black --> Result2[自動修正]
    mypy --> Result3[型の不整合を検出]

静的解析とは、プログラムを実行せずにソースコードを解析し、潜在的な問題やコードスタイルの違反を検出する手法です。英語ではStatic AnalysisまたはLintingと呼ばれます。

静的解析を導入することで、以下のメリットがあります。

  • コードの品質を一定に保てる(チーム全体で統一されたコードスタイル)
  • バグの早期発見ができる(実行前にエラーを検出)
  • コードレビューの負担軽減(スタイルの指摘をツールに任せる)
💡 ポイント
静的解析はコードを「実行しない」点がテストとの大きな違いです。テストは実行時の動作を検証しますが、静的解析はコードの構造やスタイルを検証します。

3. プロジェクトの準備

3.1 フォルダの作成

任意の場所にpython-static-analysisフォルダを作成し、Visual Studio Codeの「ファイル」→「フォルダーを開く」から、作成したpython-static-analysisフォルダを開きます。

python-static-analysis  ← このフォルダを作成

さらに、python-static-analysisフォルダの中にsrcフォルダを作成します。Visual Studio Codeのエクスプローラーでpython-static-analysisフォルダを右クリックし、「新しいフォルダー」を選択してsrcという名前で作成してください。

python-static-analysis
└── src  ← このフォルダを作成
💡 ポイント
srcフォルダには、静的解析の対象となるPythonのソースコードを配置します。解析対象のコードとプロジェクトの設定ファイル(requirements.txtなど)を分けることで、プロジェクトの構成が整理されます。

3.2 requirements.txtの作成

requirements.txtを作成します。Visual Studio Codeのエクスプローラーでpython-static-analysisフォルダを右クリックし、「新しいファイル」を選択してrequirements.txtという名前で作成してください。

python-static-analysis
├── src
└── requirements.txt  ← このファイルを作成

作成したファイルに以下の内容を記述して保存します。

flake8==7.1.1
black==24.10.0
mypy==1.13.0

各パッケージの役割は以下のとおりです。

パッケージ 役割
flake8 コードスタイルのチェックツール。PEP 8(Pythonの標準スタイルガイド)に沿っているかを検出する
black コードの自動フォーマットツール。スタイルの問題を検出するだけでなく、自動的に修正する
mypy 型チェックツール。型アノテーションをもとに、型の不整合を検出する
💡 ポイント
requirements.txtは、Pythonプロジェクトで使用するライブラリとそのバージョンを記載するファイルです。このファイルを用意しておくことで、pip install -r requirements.txtコマンドで必要なライブラリをまとめてインストールできます。

3.3 サンプルコードの作成

静的解析の対象となるサンプルコードを作成します。あえてスタイルの問題や型の不整合を含めたコードを用意します。

src/init.pyの作成

src/__init__.pyを作成します。Visual Studio Codeのエクスプローラーでsrcフォルダを右クリックし、「新しいファイル」を選択して__init__.pyという名前で作成してください。このファイルは空ファイルとして作成します。

python-static-analysis
├── src
│   └── __init__.py  ← このファイルを作成(空ファイル)
└── requirements.txt
💡 ポイント
__init__.pyは、そのフォルダがPythonのパッケージ(モジュールのまとまり)であることを示すファイルです。このファイルがないと、mypyなどのツールがsrcフォルダ内のファイルをパッケージとして認識できず、正しく解析できない場合があります。

src/calculator.pyの作成

src/calculator.pyを作成します。Visual Studio Codeのエクスプローラーでsrcフォルダを右クリックし、「新しいファイル」を選択してcalculator.pyという名前で作成してください。

python-static-analysis
├── src
│   ├── __init__.py
│   └── calculator.py  ← このファイルを作成
└── requirements.txt

作成したファイルに以下の内容を記述して保存します。

import os  # 未使用のインポート
import sys  # 未使用のインポート

def add(a,b):  # カンマの後にスペースがない
    return a+b  # 演算子の前後にスペースがない

def subtract( a, b ):  # カッコの内側に不要なスペース
    return a - b

def multiply(a, b):
    result = a * b
    return result

def divide(a, b):
    if b == 0:
        return "error"  # 他はint/floatを返すのに、ここだけstr
    return a / b

unused_variable = "this is never used"  # 未使用の変数

def evaluate_score(score):  # 条件分岐が多く、複雑度が高い関数
    if score >= 95:
        return "S"
    elif score >= 90:
        return "A+"
    elif score >= 85:
        return "A"
    elif score >= 80:
        return "B+"
    elif score >= 75:
        return "B"
    elif score >= 70:
        return "C+"
    elif score >= 65:
        return "C"
    elif score >= 60:
        return "D+"
    elif score >= 55:
        return "D"
    elif score >= 50:
        return "E"
    else:
        return "F"

このコードには、以下の問題が意図的に含まれています。

  • 未使用のインポート(os, sys
  • 関数の引数や演算子の前後にスペースが不足または過剰
  • 型の不整合(divide関数がstrfloatの両方を返す)
  • 未使用の変数(unused_variable
  • 条件分岐が多すぎる関数(evaluate_score

src/user_service.pyの作成

src/user_service.pyを作成します。Visual Studio Codeのエクスプローラーでsrcフォルダを右クリックし、「新しいファイル」を選択してuser_service.pyという名前で作成してください。

python-static-analysis
├── src
│   ├── __init__.py
│   ├── calculator.py
│   └── user_service.py  ← このファイルを作成
└── requirements.txt

作成したファイルに以下の内容を記述して保存します。

def get_user_name(user_id: int) -> str:
    users = {1: "Tanaka", 2: "Suzuki", 3: "Yamada"}
    return users.get(user_id, "Unknown")

def get_user_age(user_id: int) -> int:  # 戻り値はintと宣言しているが…
    ages = {1: 25, 2: 30, 3: 35}
    return ages.get(user_id, "N/A")  # デフォルト値がstr(型の不整合)

def format_user_info(name: str, age: int) -> str:  # 関数の前に空行が1行しかない
    return name + " (" + str(age) + "歳)"

このコードには、以下の問題が意図的に含まれています。

  • 型の不整合(get_user_age関数は戻り値をintと宣言しているが、デフォルト値として文字列"N/A"を返す可能性がある)
  • 関数定義の間の空行が1行しかない(PEP 8では2行が推奨)

3.4 ツールのインストール

requirements.txtに記載した3つのツール(flake8、black、mypy)をまとめてインストールします。Visual Studio Codeのターミナルで以下のコマンドを実行してください。

Windowsの場合:

pip install -r requirements.txt

Macの場合:

pip3 install -r requirements.txt

-r requirements.txtオプションにより、ファイルに記載されたすべてのパッケージが一括でインストールされます。

以下のようにSuccessfully installedと表示されれば、インストールは完了です。

Successfully installed black-24.10.0 flake8-7.1.1 mypy-1.13.0 ...
⚠️ インストールに失敗する場合
pip3: command not foundpip: command not foundと表示される場合は、Pythonが正しくインストールされていない可能性があります。事前準備のPythonインストール手順を確認してください。

4. Flake8 - コードスタイルチェック

Flake8は、Pythonのコードスタイルをチェックするツールです。PEP 8(Pythonの公式スタイルガイド)に準拠しているかを検証します。

4.1 Flake8の実行

以下のコマンドでFlake8を実行します。

Windowsの場合:

flake8 src/

Macの場合:

python3 -m flake8 src/

実行すると、以下のようなエラーが表示されます。

src/calculator.py:1:1: F401 'os' imported but unused
src/calculator.py:2:1: F401 'sys' imported but unused
src/calculator.py:4:1: E302 expected 2 blank lines, found 1
src/calculator.py:4:11: E231 missing whitespace after ','
src/calculator.py:5:13: E225 missing whitespace around operator
src/calculator.py:7:1: E302 expected 2 blank lines, found 1
src/calculator.py:7:14: E201 whitespace after '('
src/calculator.py:7:20: E202 whitespace before ')'
src/calculator.py:10:1: E302 expected 2 blank lines, found 1
src/calculator.py:14:1: E302 expected 2 blank lines, found 1
src/calculator.py:20:1: F841 local variable 'unused_variable' is assigned to but never used
src/calculator.py:22:1: E302 expected 2 blank lines, found 1
src/user_service.py:5:1: E302 expected 2 blank lines, found 1
src/user_service.py:9:1: E302 expected 2 blank lines, found 1

出力の読み方は以下の通りです。

  • ファイル名:行番号:列番号: エラーコード メッセージ
  • Fで始まるコードは、pyflakes由来のエラー(未使用のインポートや変数など)を示します
  • Eで始まるコードは、PEP 8のスタイル違反を示します
  • Wで始まるコードは、PEP 8のスタイル警告を示します

検出された各エラーについて解説します。

F401 'os' imported but unused

import osでインポートしていますが、コード内でosが一度も使われていません。未使用のインポートはコードの可読性を下げるため、削除すべきです。sysも同様です。

E302 expected 2 blank lines, found 1

PEP 8では、トップレベルの関数定義の前には2行の空行を入れるルールがあります。このコードでは空行が1行しかないため、エラーが検出されています。

E231 missing whitespace after ','

def add(a,b):のカンマの後にスペースがありません。PEP 8では、カンマの後にはスペースを入れるルールがあります。正しくはdef add(a, b):です。

E225 missing whitespace around operator

return a+bの演算子+の前後にスペースがありません。PEP 8では、演算子の前後にはスペースを入れるルールがあります。正しくはreturn a + bです。

E201 whitespace after '('

def subtract( a, b )のカッコ(の直後に不要なスペースがあります。PEP 8では、カッコの内側にスペースを入れないルールがあります。

E202 whitespace before ')'

同じくdef subtract( a, b )のカッコ)の直前に不要なスペースがあります。正しくはdef subtract(a, b)です。

F841 local variable 'unused_variable' is assigned to but never used

変数unused_variableに値を代入していますが、コード内で一度も使われていません。不要な変数はコードの可読性を下げるため、削除すべきです。

4.2 Flake8の設定ファイル

Flake8はデフォルトのルールでチェックを行いますが、プロジェクトによっては「1行の文字数を緩めたい」「特定のディレクトリはチェック対象外にしたい」といったカスタマイズが必要になります。設定ファイルを作成することで、プロジェクト全体で統一したルールを適用できます。

プロジェクトのルートに.flake8ファイルを作成します。Visual Studio Codeのエクスプローラーでpython-static-analysisフォルダを右クリックし、「新しいファイル」を選択して.flake8という名前で作成してください。

python-static-analysis
├── src
│   ├── __init__.py
│   ├── calculator.py
│   └── user_service.py
├── .flake8  ← このファイルを作成
└── requirements.txt

作成したファイルに以下の内容を記述して保存します。

[flake8]
max-line-length = 120
max-complexity = 10
exclude =
    .git,
    __pycache__,
    .venv
ignore = E203, W503, E302

各設定項目について解説します。

max-line-length = 120

1行の最大文字数を120文字に変更しています。PEP 8のデフォルトは79文字ですが、現代のモニタは横幅が広いため、多くのプロジェクトでは100〜120文字に緩和しています。今回のサンプルコードには79文字を超える行がないため、この設定による出力の変化はありません。

max-complexity = 10

関数の循環的複雑度(条件分岐やループの多さを示す指標)の上限を10に設定しています。これを超える複雑な関数がある場合、C901エラーが報告されます。Flake8はデフォルトでは循環的複雑度をチェックしないため、先ほどの実行結果にはC901が含まれていませんでした。この設定を追加することで、evaluate_score関数のように条件分岐が多い関数が新たに検出されるようになります。

exclude =
    .git,
    __pycache__,
    .venv

チェック対象から除外するディレクトリを指定しています。.git(Gitの管理ファイル)、__pycache__(Pythonのキャッシュ)、.venv(仮想環境)はプロジェクトのソースコードではないため、チェック対象外にしています。今回のプロジェクトにはこれらのディレクトリがないため、この設定による出力の変化はありません。

ignore = E203, W503, E302

特定のエラーコードを無視する設定です。

エラーコード 説明 無視する理由
E203 スライス記法のスペース 次のセクションで紹介する自動フォーマットツールのルールと競合するため
W503 演算子の前での改行 同上
E302 関数定義前の空行不足 次のセクションで自動修正されるため

先ほどの実行結果ではE302が7件検出されていました。ignoreE302を追加することで、これらのエラーが出力されなくなります。

設定ファイルを作成した後、再度Flake8を実行して変化を確認してみましょう。

Windowsの場合:

flake8 src/

Macの場合:

python3 -m flake8 src/

以下のように、先ほどの結果からE302のエラー7件がすべて消え、代わりにC901のエラーが新たに検出されていることが確認できます。

src/calculator.py:1:1: F401 'os' imported but unused
src/calculator.py:2:1: F401 'sys' imported but unused
src/calculator.py:4:11: E231 missing whitespace after ','
src/calculator.py:5:13: E225 missing whitespace around operator
src/calculator.py:7:14: E201 whitespace after '('
src/calculator.py:7:20: E202 whitespace before ')'
src/calculator.py:20:1: F841 local variable 'unused_variable' is assigned to but never used
src/calculator.py:22:1: C901 'evaluate_score' is too complex (12)

ignoreに指定したE302が出力されなくなった一方で、max-complexity = 10の設定により、evaluate_score関数の複雑度が12と判定され、新たにC901エラーが検出されました。このように、設定ファイルを使うことで不要なチェックを抑制しつつ、新しいチェックを追加することができます。

max-line-lengthexcludeの設定は、今回のサンプルコードでは出力に影響しませんが、実際のプロジェクトでは長い行やチェック不要なディレクトリが出てくるため、あらかじめ設定しておくことが一般的です。

5. Black - コード自動フォーマット

Blackは、Pythonのコードフォーマッタです。Flake8がスタイル違反を「指摘」するのに対し、Blackはコードを自動的に「修正」します。Blackは「The Uncompromising Code Formatter」(妥協のないコードフォーマッタ)を謳っており、設定項目が少なく、チーム全体で統一されたスタイルを強制できます。

5.1 フォーマット前の確認

まず、Blackが何を変更するかを確認するために、--checkオプションで実行します。

Windowsの場合:

black --check src/

Macの場合:

python3 -m black --check src/

以下のように、フォーマットが必要なファイルが表示されます。

would reformat src/calculator.py
would reformat src/user_service.py
Oh no! 💥 💔 💥
2 files would be reformatted.

calculator.pyuser_service.pyにフォーマットが必要な箇所があることが検出されています。--checkオプションはコードを変更せず、確認のみを行います。

5.2 Blackの実行

以下のコマンドでBlackを実行し、コードを自動フォーマットします。

Windowsの場合:

black src/

Macの場合:

python3 -m black src/

以下のように、フォーマットが実行された結果が表示されます。

reformatted src/calculator.py
reformatted src/user_service.py
All done! ✨ 🍰 ✨
2 files reformatted.

calculator.pyuser_service.pyの両方が自動フォーマットされたことが表示されています。

フォーマット後のsrc/calculator.pyを確認すると、スペースの問題が自動的に修正されていることがわかります。

import os
import sys


def add(a, b):
    return a + b


def subtract(a, b):
    return a - b


def multiply(a, b):
    result = a * b
    return result


def divide(a, b):
    if b == 0:
        return "error"
    return a / b


unused_variable = "this is never used"


def evaluate_score(score):
    if score >= 95:
        return "S"
    elif score >= 90:
        return "A+"
    elif score >= 85:
        return "A"
    elif score >= 80:
        return "B+"
    elif score >= 75:
        return "B"
    elif score >= 70:
        return "C+"
    elif score >= 65:
        return "C"
    elif score >= 60:
        return "D+"
    elif score >= 55:
        return "D"
    elif score >= 50:
        return "E"
    else:
        return "F"
📝 Flake8とBlackの違い
Flake8は問題を「検出」し、Blackは問題を「自動修正」します。両方を併用することで、自動修正できない論理的な問題(未使用のインポートなど)もFlake8で検出できます。

5.3 Blackの設定

BlackもFlake8と同様に、プロジェクトに合わせた設定のカスタマイズができます。たとえば、Blackはデフォルトで1行の最大文字数が88文字に設定されていますが、Flake8の.flake8ファイルではmax-line-length = 120に設定しました。このままでは、Blackが88文字で折り返したコードをFlake8が問題なしと判定するなど、ツール間でルールが食い違う可能性があります。

Blackの設定はpyproject.tomlファイルに記述します。プロジェクトのルートにpyproject.tomlを作成します。Visual Studio Codeのエクスプローラーでpython-static-analysisフォルダを右クリックし、「新しいファイル」を選択してpyproject.tomlという名前で作成してください。

python-static-analysis
├── src
│   ├── __init__.py
│   ├── calculator.py
│   └── user_service.py
├── .flake8
├── pyproject.toml  ← このファイルを作成
└── requirements.txt

作成したファイルに以下の内容を記述して保存します。

[tool.black]
line-length = 120

line-length = 120により、Blackが1行を折り返す基準を120文字に変更しています。これでFlake8のmax-line-length = 120と統一され、ツール間でルールが矛盾しなくなります。

Blackは「妥協のないフォーマッタ」を謳っており、意図的に設定項目が少なく設計されています。主な設定項目は以下のとおりです。

設定項目 説明 デフォルト値
line-length 1行の最大文字数 88
target-version 対象のPythonバージョン(例: ["py312"] 自動検出
skip-string-normalization 文字列のクォート統一(シングル→ダブル)を無効化 false
extend-exclude 除外するファイル・フォルダのパターンを追加 なし

今回のハンズオンではline-lengthのみ設定していますが、必要に応じて他の設定も追加できます。

6. mypy - 型チェック

mypyは、Pythonの静的型チェッカです。Pythonは動的型付け言語のため、変数や関数の引数にどんな型の値でも入れることができます。これは柔軟である反面、意図しない型の値が渡されてもエラーにならず、実行時に初めて問題が発覚することがあります。

Pythonでは、型ヒント(Type Hints) を記述することで、コードに「この変数はint型」「この関数はstrを返す」といった型の情報を付けることができます。mypyはこの型ヒントをもとに、実行前に型の不整合を検出します。

6.1 型ヒントの基本

Pythonでは、関数の引数や戻り値に型ヒントを付けることができます。

def greet(name: str) -> str:
    return "Hello, " + name

def calculate_total(price: int, quantity: int) -> int:
    return price * quantity
  • name: str は引数namestr型であることを示す
  • -> str は戻り値がstr型であることを示す
💡 ポイント
型ヒントはあくまで「注釈」であり、Pythonの実行時には強制されません。型ヒントに反する値を渡してもプログラムはそのまま動作します。mypyのような静的型チェッカを使って初めて、型の不整合を検出できます。

6.2 mypyの実行

以下のコマンドでmypyを実行します。

Windowsの場合:

mypy src/

Macの場合:

python3 -m mypy src/

実行すると、以下のようなエラーが表示されます。

src/user_service.py:8: error: Incompatible return value type (got "int | str", expected "int")  [return-value]
Found 1 error in 1 file (checked 2 source files)

出力の読み方は以下の通りです。

  • ファイル名:行番号: error: メッセージ [エラーカテゴリ]
  • 最終行にはエラーの合計件数とチェックしたファイル数が表示される

検出されたエラーについて解説します。

Incompatible return value type (got "int | str", expected "int")  [return-value]

get_user_age関数の戻り値の型はintと宣言されています。しかし、ages.get(user_id, "N/A")ではキーが見つからない場合に文字列"N/A"を返すため、戻り値がintまたはstrになります。宣言した型と実際に返す型が一致しないことをmypyが検出しています。

💡 ポイント
Flake8はコードの「見た目」(スタイル)をチェックしますが、mypyはコードの「意味」(型の整合性)をチェックします。mypyが検出するのは、実行時にバグになりうる型の不整合です。

6.3 エラーの修正

型の不整合を修正するために、src/user_service.pyget_user_age関数を以下のように修正します。

def get_user_age(user_id: int) -> int:
    ages = {1: 25, 2: 30, 3: 35}
    return ages.get(user_id, 0)

デフォルト値を文字列"N/A"から数値0に変更することで、戻り値の型が常にintになり、宣言と一致します。

修正後に再度mypyを実行して、エラーが解消されたことを確認しましょう。

Windowsの場合:

mypy src/

Macの場合:

python3 -m mypy src/

以下のように、エラーが解消されたことが表示されます。

Success: no issues found in 2 source files

6.4 mypyの設定

mypyもFlake8やBlackと同様に、プロジェクトに合わせた設定のカスタマイズができます。mypyの設定はBlackと同じくpyproject.tomlファイルに記述します。

設定を行う理由は主に2つあります。1つ目は、チェック対象のPythonバージョンを明示することで、チーム全員が同じ基準でチェックできるようにすることです。2つ目は、デフォルトでは無効になっているより厳格なチェックルールを有効にすることで、型の不整合をより多く検出できるようにすることです。

先ほど作成したpyproject.tomlに以下の内容を追加します。

[tool.black]
line-length = 120

[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true

追加したコードを解説します。

[tool.mypy]

mypyの設定セクションの開始を示しています。Blackの[tool.black]と同様に、pyproject.tomlではツールごとにセクションを分けて設定を記述します。

python_version = "3.12"

チェック対象のPythonバージョンを指定しています。指定したバージョンで利用できない構文や型を使った場合にエラーが報告されます。チーム内で使用するPythonバージョンを統一するために設定します。

warn_return_any = true

戻り値の型がAny(型が不明)になっている場合に警告を出す設定です。デフォルトでは無効になっていますが、有効にすることで型チェックの漏れを防ぐことができます。

warn_unused_configs = true

設定ファイル内で使われていない設定項目がある場合に警告を出す設定です。設定の記述ミスを早期に発見するために有効にしています。

💡 ポイント
今回追加したwarn_return_anywarn_unused_configsは、サンプルコードでは該当するケースがないため、出力結果に変化はありません。しかし、実際のプロジェクトではこれらの設定が問題の早期発見に役立ちます。

mypyにはこのほかにも多くの設定項目があります。主な設定項目は以下のとおりです。

設定項目 説明 デフォルト値
python_version チェック対象のPythonバージョン 実行環境のバージョン
warn_return_any 戻り値がAny型の場合に警告 false
warn_unused_configs 未使用の設定項目を警告 false
disallow_untyped_defs 型ヒントのない関数定義をエラーにする false
ignore_missing_imports インポート先の型情報がない場合のエラーを無視 false

今回のハンズオンでは基本的な設定のみですが、プロジェクトの規模が大きくなるにつれて、disallow_untyped_defsなどのより厳格なチェックを段階的に導入していくことが一般的です。

7. VS Codeとの連携

ここまで、ターミナルからコマンドを実行して静的解析を行ってきました。しかし、毎回コマンドを手動で実行するのは手間がかかります。VS Codeの拡張機能を使うことで、コードを編集・保存するたびに自動的にチェックやフォーマットが実行されるようになります。

7.1 拡張機能のインストール

以下の4つの拡張機能をVS Codeにインストールします。VS Codeの左側のサイドバーから「拡張機能」アイコン(四角が4つ並んだアイコン)をクリックし、検索バーに拡張機能名を入力してインストールしてください。

拡張機能名 説明
Python(Microsoft) Python開発の基本拡張機能。他の3つの拡張機能が動作するために必要
Flake8(Microsoft) Flake8をVS Codeに統合し、コードのスタイル違反をエディタ上にリアルタイム表示する
Black Formatter(Microsoft) BlackをVS Codeに統合し、コードの自動フォーマットをエディタから実行できるようにする
Mypy Type Checker(Microsoft) mypyをVS Codeに統合し、型の不整合をエディタ上にリアルタイム表示する

拡張機能をインストールすると、Flake8やmypyのチェック結果がエディタ上に波線で表示されるようになります。波線にマウスカーソルを合わせると、エラーの内容が確認できます。

💡 ポイント
拡張機能をインストールした後、VS Codeを再起動すると確実に反映されます。また、プロジェクトで使用しているPythonインタプリタが正しく選択されているか確認してください。VS Code下部のステータスバーに表示されているPythonバージョンをクリックすると、インタプリタを切り替えることができます。

7.2 保存時の自動フォーマット設定

Black Formatter拡張機能をインストールしただけでは、自動フォーマットは有効になりません。ファイルを保存するたびにBlackで自動フォーマットされるように設定を行います。

VS Codeのコマンドパレットを使ってsettings.jsonを開きます。Windowsの場合はCtrl + Shift + P、Macの場合はCmd + Shift + Pのキーボードショートカットでコマンドパレットを開いてください。

コマンドパレットが開いたら、Preferences: Open User Settings (JSON)と入力し、表示された候補を選択します。settings.jsonファイルが開きます。

settings.jsonを初めて編集する場合は、ファイルの内容が{}のみになっています。その場合は、以下の内容をそのまま記述してください。

{
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true
    }
}

すでに他の設定が記述されている場合は、既存の設定を消さないように注意してください。以下の例のように、既存の設定の最後の行にカンマを追加し、その後に[python]の設定を追記します。

{
    "editor.minimap.enabled": false,
    "git.confirmSync": false,
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true
    }
}

この例では、"git.confirmSync": falseの末尾にカンマを追加し、その後に"[python]"の設定ブロックを追記しています。

📝 JSON形式の注意点
settings.jsonはJSON形式のため、設定項目の間にはカンマが必要です。カンマが不足していたり、最後の項目の後にカンマがあるとエラーになります。追記した後、ファイル内に赤い波線が表示されていないか確認してください。

各設定項目の意味は以下のとおりです。

  • "editor.defaultFormatter": "ms-python.black-formatter" は、PythonファイルのフォーマッタとしてBlack Formatterを使用する設定です
  • "editor.formatOnSave": true は、ファイルを保存するたびに自動的にフォーマットを実行する設定です

この設定により、今後Pythonファイルを保存するたびにBlackによるフォーマットが自動的に実行されます。先ほどのハンズオンではターミナルからblack src/コマンドを手動で実行しましたが、この設定を行うことでコマンドを実行する手間がなくなり、常にフォーマットされた状態を保つことができます。

8. まとめ

このハンズオンでは、Pythonの静的解析ツールの使い方を体験しました。

  • 静的解析はコードを実行せずに問題を検出する手法であり、コード品質の維持に不可欠
  • Flake8はPEP 8に基づくコードスタイルチェッカで、スタイル違反や未使用のインポートを検出する
  • Blackはコードフォーマッタで、コードスタイルを自動的に統一する
  • mypyは静的型チェッカで、型ヒントに基づいて型の不整合を検出する
  • Flake8は問題の「検出」、Blackは問題の「自動修正」を行うため、両方を併用することが推奨される
  • VS Codeの拡張機能を使うことで、開発中にリアルタイムで静的解析を実行できる