Pythonの基本的なエラー一覧とその原因の確認方法
Pythonの基本的なエラー・例外の一覧とその原因の確認方法について説明する。原因が明らかになればそれを修正するのは簡単。
以下の内容について説明する。
エラーと例外
Pythonにおいて、エラーは構文エラー(syntax error)と例外(exception)に区別される。
構文として誤っているものは構文エラー、構文として正しくても実行中に発生するエラーは例外と呼ばれる。
エラーには (少なくとも) 二つのはっきり異なる種類があります。それは 構文エラー (syntax error) と 例外 (exception) です。
…
実行中に検出されたエラーは 例外 (exception) と呼ばれ、常に致命的とは限りません。
8. エラーと例外 — Python 3.6.5 ドキュメント
ここでは想定内の例外を捕捉し対応する例外処理ではなく、想定外のエラー・例外の原因の確認方法について説明する。例外処理については以下の記事を参照。
なお、以降は「エラー」と「例外」を特に使い分けず、すべて「エラー」と呼ぶ。
エラーメッセージの内容
エラーが発生すると以下のようなエラーメッセージが出力される。エラーが発生したファイル名、および、エラー箇所が行番号とともに表示され、最終行にはエラーの内容と具体的な説明が示される。
l = 100
l.append(200)
# Traceback (most recent call last):
# File "/Users/mbp/Documents/my-project/python-snippets/errors.py", line 2, in <module>
# l.append(200)
# AttributeError: 'int' object has no attribute 'append'
AttributeError
やTypeError
などのような最終行の内容を確認することでエラーの原因が推測できる。コロン:
のあとの詳細説明はそれほど難しい英文ではないので英語が苦手でもしっかり読むべき。
以下、基本的なエラーの一覧をエラー箇所およびエラーメッセージをコメントアウトしたコードと修正したコードとともに例示する。
そのほかすべての組み込み例外は公式ドキュメントを参照。
構文に関するエラー
Pythonの構文として正しくない場合のエラー。高機能なエディタやIDEを使っていれば実行前にチェックしてくれることが多い。
SyntaxError
括弧()
やコロン:
が足りない場合などのエラー。
# print('hello'
# SyntaxError: unexpected EOF while parsing
print('hello')
# hello
# for i in range(3)
# print(i)
# SyntaxError: invalid syntax
for i in range(3):
print(i)
# 0
# 1
# 2
IndentationError
インデントが正しくない場合のエラー。
同じ階層であるべきインデントが一致していなかったりする場合など。
n = 100
# if n == 100:
# print('n is 100')
# else:
# print('n is not 100')
# IndentationError: unindent does not match any outer indentation level
n = 100
if n == 100:
print('n is 100')
else:
print('n is not 100')
# n is 100
インポートに関するエラー
ModuleNotFoundError
モジュールが見つからないというエラー。
# import mathematics
# ModuleNotFoundError: No module named 'mathematics'
import math
print(math.pi)
# 3.141592653589793
そもそも対象のモジュールがインストールされていないか、自作のモジュールの場合は検索パスの設定が間違っている可能性がある。
モジュール内のオブジェクトを直接インポートしようとした場合もエラーとなる。オブジェクトを直接インポートする場合はfrom
を使う。
# import math.pi
# ModuleNotFoundError: No module named 'math.pi'; 'math' is not a package
from math import pi
print(pi)
# 3.141592653589793
インポートに関する詳細は以下の記事を参照。
ModuleNotFoundError
はバージョン3.6で追加された。それより前のバージョンでは次に説明するImportError
が送出される。
確認項目は以下の通り。
- モジュール名は正しいか
- 対象のモジュールが本当にインストールされているか
pip list
コマンドなどでインストールされているモジュールを確認
- モジュール検索パスは正しく設定されているか
ImportError
from <モジュール名> import <オブジェクト名(関数名など)>
でモジュールに含まれていないオブジェクトをインポートしようとしたときなどのエラー。
大文字小文字も区別されるので注意。
# from math import COS
# ImportError: cannot import name 'COS' from 'math' (/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/lib-dynload/math.cpython-37m-darwin.so)
from math import cos
print(cos(0))
# 1.0
確認項目は以下の通り。
- モジュール名、オブジェクト名は正しいか
- 対象のモジュールに本当にそのオブジェクトが含まれているか
- 公式ドキュメントなどを確認
型や値、名前に関するエラー
AttributeError
属性(Attribute
)参照に関するエラー。
<オブジェクト>.<識別子>
のようにメソッドなどを呼び出す際に、オブジェクトや識別子(属性やメソッド)の名前、オブジェクトの型を間違えている場合に発生する。大文字小文字も区別される。
識別子の名前を間違えている例。
import math
# print(math.PI)
# AttributeError: module 'math' has no attribute 'PI'
print(math.pi)
# 3.141592653589793
オブジェクトの型が想定と異なっている例。
l = 100
# l.append(200)
# AttributeError: 'int' object has no attribute 'append'
l = [100]
l.append(200)
print(l)
# [100, 200]
確認項目は以下の通り。
- オブジェクト名、識別子名は正しいか
- オブジェクトの型は想定通りか
TypeError
不適切な型に対して演算や組み込み関数による処理が行われた場合のエラー。
異なる型のオブジェクトを+
演算子で加算しようとした場合や、文字列や数値を浮動小数点型(float
)に変換する組み込み関数float()
にそのほかの型のオブジェクトを渡した場合など。
n = '100'
# print(n + 200)
# TypeError: can only concatenate str (not "int") to str
n = 100
print(100 + 200)
# 300
# print(float(['1.23E-3']))
# TypeError: float() argument must be a string or a number, not 'list'
print(float('1.23E-3'))
# 0.00123
確認項目は以下の通り。
- 演算するオブジェクトの型は正しいか
- 関数に渡すオブジェクトの型は正しいか
ValueError
型は合っているが値が適切でない場合のエラー。
例えばfloat()
は文字列(str
)を浮動小数点(float
)に変換するが、元の文字列が変換可能な値でないとエラーになる。
# print(float('float number'))
# ValueError: could not convert string to float: 'float number'
print(float('1.23E-3'))
# 0.00123
確認項目は以下の通り。
- 関数に渡す値は適切か
ZeroDivisionError
0で割り算が行われた場合のエラー。
除算/
だけでなく、整数除算//
、剰余演算%
でも発生する。
n = 100
zero = 0
# print(n / zero)
# ZeroDivisionError: division by zero
# print(n // zero)
# ZeroDivisionError: integer division or modulo by zero
# print(n % zero)
# ZeroDivisionError: integer division or modulo by zero
変数で割る場合、除算の前段階で期せずしてゼロになってしまっている可能性がある。
確認項目は以下の通り。
- 除数(割る数)がゼロになっていないか
NameError
名前が見つからなかった場合のエラー。
変数名のスペル間違いなど。 大文字小文字も区別されるので注意。
my_number = 100
# print(myNumber)
# NameError: name 'myNumber' is not defined
print(my_number)
# 100
確認項目は以下の通り。
- 対象の変数は定義されているか
- スペルは正しいか
インデックスやキーに関するエラー
IndexError
リストやタプルなどのシーケンスオブジェクトに格納された値を[インデックス]
で取得する際に、範囲外の位置(要素数を超えたインデックス値)を指定してしまった場合のエラー。
リストやタプルの要素数はlen()
で確認可能。
- 関連記事: Pythonでリストのサイズ(要素数)を取得
l = [0, 1, 2]
# print(l[100])
# IndexError: list index out of range
print(len(l))
# 3
print(l[1])
# 1
確認項目は以下の通り。
- シーケンスオブジェクトの要素数は正しいか
- インデックスとして指定した値は正しいか
KeyError
辞書(dict
型)の値をキーを指定して取得する際に、存在しないキーを指定してしまった場合のエラー。
d = {'a': 1, 'b': 2, 'c': 3}
# print(d['x'])
# KeyError: 'x'
print(d['a'])
# 1
キーの一覧はkeys()
メソッドで確認可能。
print(d)
# {'a': 1, 'b': 2, 'c': 3}
print(list(d.keys()))
# ['a', 'b', 'c']
get()
メソッドを使うと存在しないキーに対してもエラーにならずデフォルト値を取得できる。
print(d.get('x'))
# None
確認項目は以下の通り。
- 辞書に含まれるキーは正しいか
- 指定したキーは正しいか
ファイルやディレクトリに関するエラー
FileNotFoundError
open()
でファイルを読み込む際などに指定したファイルが見つからない場合のエラー。
# with open('not_exist_file.txt') as f:
# print(f.read())
# FileNotFoundError: [Errno 2] No such file or directory: 'not_exist_file.txt'
相対パスで指定した場合は、Pythonのカレントディレクトリが想定と異なっている可能性もある。
確認項目は以下の通り。
- 指定したファイルは本当に存在しているか
- 指定したパスは正しいか
- 相対パスで指定した場合、カレントディレクトリは正しいか
FileExistsError
すでに存在しているファイルやディレクトリを作成しようとした場合のエラー。
import os
# os.mkdir('data')
# FileExistsError: [Errno 17] File exists: 'data'
バージョン3.2以降のos.makedirs()
では引数exist_ok
が追加されており、exist_ok=True
とするとすでに存在しているディレクトリを作成しようとしてもエラーにならない。
確認項目は以下の通り。
- 指定したファイル・ディレクトリがすでに存在していないか