mypyの型チェックは通るのに実行時に TypeError: 'method' object is not subscriptable が発生する場合
概要
ライブラリのクラスなどの型パラメータを指定するとmypyによる型チェックは通るものの実行時にエラーになってしまう場合があります。 その対処法と、このエラーが発生する理由について書きます。
from multiprocessing import Queue q: Queue[int] = Queue()
$ mypy main.py Success: no issues found in 1 source file $ python main.py Traceback (most recent call last): File "xxx/main.py", line 3, in <module> q: Queue[int] = Queue() TypeError: 'method' object is not subscriptable
対処法
Using classes that are generic in stubs but not at runtimeに書かれている通り、3種類の対応方法があります。
Python 3.7以上を使っている場合
from __future__ import annotations
により実行時エラーが発生しなくなります。
from __future__ import annotations from multiprocessing import Queue q: Queue[int] = Queue()
文字列リテラルを使用
from multiprocessing import Queue q: 'Queue[int]' = Queue()
型チェックとランタイムで切り替え
from multiprocessing import Queue from typing import TYPE_CHECKING if TYPE_CHECKING: IntQueue = Queue[int] else: IntQueue = Queue q: IntQueue = Queue()
実行時エラーが発生する理由
PEP 484 には、型ヒントについて次のように書かれています。
Annotations must be valid expressions that evaluate without raising exceptions at the time the function is defined
アノテーションは例外を発生させない式でなければなりません。
Queue[int]
を式として評価したとき、 Queue
(のメタクラス)が __getitem__
を実装していないためにエラーが発生します。
そのため、 TypeError: 'method' object is not subscriptable
というエラーが発生します。