mypy

【Python】mypyを使用した型チェックの方法

【Python】mypyを使用した型チェックの方法

Pythonの型ヒントを利用して型チェックをすることができるmypyの使い方について解説します。

Pythonの型ヒント(型アノテーション)とmypy

Pythonでは、バージョン3.5から型ヒント(型アノテーション)がサポートされています。型ヒントの基本については「型ヒント(変数・関数の型アノテーション)の基本」でまとめていますので興味があれば参考にしてください。

Pythonの型ヒントは単なる注釈であり、プログラム実行に制約を加えません。Pythonは変数や関数の型アノテーションを強制もしません。

Pythonは動的型付け言語であり、型を明示する必要がないため、プログラミング初学者にとって学習しやすいという利点があります。しかし、変数や関数の誤った使い方によってバグが生じることもあります。

型ヒントを使用する場合、適切な型を使用しているかどうか型チェックをしたくなることがあるでしょう。Pythonで型チェックをしたい場合、mypyというライブラリを使用できます。mypyは、型ヒントを基にプログラムの実行前に型のチェックをするサードパーティ製のライブラリです。

この記事では、mypyでPythonコードの型チェックをする方法を紹介します。

mypyを使用した型チェック

mypyのインストール

mypyを使用するには以下のようにpipでインストールしてください。

pip install mypy

記事執筆時点では、mypyはPython3.8以降を必要としていますが、最新の情報は公式ドキュメントのGetting startedのページを確認するようにしてください。

mypyの基本的な使い方

mypyの実行方法

mypyは、コマンドラインインターフェースで以下のように実行することができます。program_name.pyの部分にはチェック対象のプログラムを指定してください。

mypy program_name.py

以降では、簡単な例を使ってmypyの型チェックの実行結果を見てきます。

変数の型チェック

変数の使用に関する型チェックをする場合の例について見てみます。

型チェックが問題ない場合

mypyを実行した際に変数の型チェックに問題がない場合は、以下のようにSuccessと表示されます。

# intの型アノテーション
x: int = 10
print(x)

# 正しい型(int)を代入する
x = 20
print(x)
[mypy実行結果]
Success: no issues found in 1 source file

上記例では、int型で定義しているxという変数をintとして扱っているため問題はありません。

型チェックに問題がある場合

mypyを実行した際に変数の型チェックに問題がある場合は、以下のようにエラーが表示されます。

# intの型アノテーション
x: int = 10
print(x)

# 異なる型(str)を代入する
x = "Test"
print(x)
[mypy実行結果]
variable_error.py:6: error: Incompatible types in assignment (expression has type "str", variable has type "int")  [assignment
]
Found 1 error in 1 file (checked 1 source file)

上記例では、int型で定義しているxという変数に、str型の値を代入しようとしているためエラーが出力されています。このように、変数の使用に関する型チェックが可能です。

関数の型チェック

関数の使用に関する型チェックをする場合の例について見てみます。

型チェックが問題ない場合

mypyを実行した際に関数の型チェックに問題がない場合は、以下のようにSuccessと表示されます。

def func_annotation(x: int, y: int) -> int:
    return x * y


if __name__ == "__main__":
    val1 = 10
    val2 = 3
    
    # 正しい型で使用する
    print(func_annotation(val1, val2))
[mypy実行結果]
Success: no issues found in 1 source file

上記例では、関数の型アノテーションに従った値を引数として指定しているため問題はありません。

型チェックに問題がある場合

mypyを実行した際に関数の型チェックに問題がある場合は、以下のようにエラーが表示されます。

def func_annotation(x: int, y: int) -> int:
    return x * y


if __name__ == "__main__":
    val1 = "test"
    val2 = 3

    # 引数xを誤った型(str)で使用する
    print(func_annotation(val1, val2))
[mypy実行結果]
func_error.py:8: error: Argument 1 to "func_annotation" has incompatible type "str"; expected "int"  [arg-type]
Found 1 error in 1 file (checked 1 source file)

上記例では、int型で定義しているxという引数に、str型の値を代入しようとしているためエラーが出力されています。このように、関数の使用に関する型チェックが可能です。

設定ファイルによるカスタマイズ

mypyは、mypy.iniという設定ファイルで実行に関する設定を行えます。mypy.iniファイルは、コードと同じ階層か、プロジェクトルートに配置します。mypy.iniの参照順序は、公式ドキュメントの設定ファイルのページに記載があります。また、設定ファイルとしては、mypi.iniの代わりにpyproject.tomlも使用できます。

mypy.iniでは、以下のような内容を設定します。

[mypy]
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True

[mypy]の部分はmypyのグローバル設定となっており、各設定項目にはTrueまたはFalseを指定します。

特定のパッケージに設定を適用させたい場合、[mypy-mycode.foo.*]のようなブロックを作成し、その中に設定を記述することができます。この設定は、mycode.fooパッケージ内に適用されます。mypy.iniの設定例は、公式ドキュメントの例のページに記載がありますので参考にしてください。

warn_return_anyは、関数がAny型持つと推測される値を返すたびにエラーを通知します。また、warn_unsed_configsはmypyが使用していない設定オプションを使用していることを通知します。これらの設定については、公式ドキュメントの例に詳細な情報が掲載されています。

disallow_untyped_defsは、型ヒントを設定していない関数定義がある場合にエラーを出力します。例えば、disallow_untyped_defs=Trueとして、以下のような型ヒントの不足した関数をチェックするとエラーが表示されます。

# 型アノテーションを指定する場合
# アノテーションの指定が不十分
def func_annotation(x: int, y):
    return x * y


if __name__ == "__main__":
    val1 = "test"
    val2 = 3
    print(func_annotation(val1, val2))
【mypy実行結果】
PS D:\PycharmProjects\python-tech-sample-source\python-libraries\mypy\basics> mypy .\func_error_not_enough_hint.py
func_error_not_enough_hint.py:3: error: Function is missing a return type annotation  [no-untyped-def]
func_error_not_enough_hint.py:3: error: Function is missing a type annotation for one or more arguments  [no-untyped-def]
func_error_not_enough_hint.py:10: error: Argument 1 to "func_annotation" has incompatible type "str"; expected "int"  [arg-typ
e]
Found 3 errors in 1 file (checked 1 source file)

上記の例では、yの型アノテーションが不足しているエラーと、返り値の型アノテーションが不足しているエラーが表示されています。disallow_untyped_defsを設定しないか、Falseに設定する場合、これらのエラーは表示されません。

関数の型アノテーションを正確に指定したい場合は、disallow_untyped_defs=Trueに設定すると良いでしょう。

まとめ

Pythonの型ヒントを利用して型チェックをすることができるmypyの使い方について解説しました。

mypyは、型ヒントを基にプログラムの実行前に型のチェックをすることができるサードパーティ製のライブラリです。この記事では、変数と関数の型チェックやmypy.iniという設定ファイルについて紹介しました。

Pythonの型ヒントは、単なる注釈であるため、プログラム実行に制約を加えません。Pythonは変数や関数の型アノテーションを強制しないため自由度が高いです。型ヒントを設定する場合、型のチェックを行いたくなることがあると思います。このような場合にはmypyの活用を検討する価値があると思います。

Note

mypyの公式ドキュメントはこちらを参照してください。