プログラムに文字列のクォートの閉じ忘れのような「構文エラー(SyntaxError
)」があるとPythonはすぐさまエラーを表示します。
一方、構文エラーを修正し、無事プログラムを実行できても、予想外のデータが入力されたりすると今度は「例外(Exception
)」発生をエラーで通知します。例外とはプログラム実行時に生じた想定外の「例外」です。例えば、文字列を入力すべき箇所に数値が入力された、読み込むファイルがない、などの「例外」が検知されるとエラーで教えてくれます。
このようにPythonでは構文エラーと例外発生時にエラーを表示します。
エラーの対策は必須ですが、その前にまず原因を把握する必要があります。講座のなかでも適時説明しましたが、今回「見方とよくあるエラー」をまとめましたので、参考にしてください。
構文エラー、例外、バグは区別してください
構文エラーがあるとプログラムを実行できません。プログラムを実行できても、処理できないデータの入力など例外が検知されるとエラーを表示します。バグとは、「プログラム中の誤り」全般のことですが、ロジックの間違いに起因する場合は、ほとんど例外では検出できないので、こちらの方が対策が難しくなります。
本記事の目次
エラーの見方
IDLEでPythonファイルを実行した場合、エラーは以下のように表示されます。
◯「構文エラー」の場合
プログラムに構文の間違えがあると、以下のように構文エラー(SyntaxError
)をダイアログで表示します。同時に該当箇所を赤いハイライトで示してくれます。
IDLEではメッセージが上のようなダイアログで表示されます。
この例では「EOL while scanning string literal
(文字列の値をスキャンしているうちに行末まで来てしまいました)」と表示されています。これから、行内にクォートがあるのに、行末(EOL:End Of Line)までに閉じるクォートを探せなかった、つまりクォートの閉じ忘れが原因であると分かります。
◯「例外」の場合
例外(Exception
)が検知されると以下のように赤い文字でその内容が出力されます。最初にTraceback (most recent call last):
と表示されて、最後にエラーの内容が表示されます。
今回の例では、実際に例外が発生しているのはTracebackの最後にある~ zipfile.py", line 1204, ~
からzipfile.pyの1204行とわかります。さらにこのコードを呼び出しているのは、その上の~ phys_pkg.py", line 101, ~
からphys_pkg.pyの101行です。
このように呼び出し履歴を上方向に遡ってゆくと、例外の原因となる自分のコードに辿り着きます。この呼び出し履歴を遡って追跡することを「Traceback」と言います。
ここでは、最後にあるエラーの内容がFileNotFoundError: [Errno 2] No such file or directory: ~
と表示されているので、「指定したファイルかディレクトリが見当たらない」ために例外が発生していることが分かります。
そして、Tracebackを一番上まで辿ると自分のコード(docx_extract_text.py
)の8行目がエラーの発端になっていることが判明します。そこをチェックし修正します。
[Errno 2]
の2
ように番号も表示されますが、その後に続くメッセージ(No such file or directory
)と対応しています。つまり、エラー番号2
とはNo such file or directory
のエラーのことを差します。
よくあるエラー
ここからは、IDLEの対話モード(インタラクティブシェル)を用いて、簡単なコードでよくあるエラーを再現してみます。他のエラーや詳細については以下の公式ドキュメントを参照してください。
よくあるエラーの一覧
- SyntaxError
- NameError
- TypeError
- ValueError
- IndexError
- KeyError
- ModuleNotFoundError
- FileNotFoundError
- UnicodeDecodeError / UnicodeEncodeError
SyntaxError
Pytyonが解釈できない構文があると、以下のように構文エラー(SyntaxError
)になります。IDLEでは該当する箇所を赤くハイライトしてくれます。コマンドプロンプトやターミナルでは、^
で示してくれます。
>>> 1 +* 3
SyntaxError: invalid syntax
IDLEでは、インデントに関する間違いもSyntaxError
として表示されます。
>>> def calc_liner(x,a,b):
y = a * x + b
return y
SyntaxError: unexpected indent
その他に、インデントに関するエラーでは以下のようなメッセージが表示されることがあります。
# インデントがない場合
SyntaxError: expected an indented block
# インデントに「タブ」と「スペース」が混在している場合
SyntaxError: inconsistent use of tabs and spaces in indentation
# インデントのレベルが一致していない場合
SyntaxError: unindent does not match any outer indentation level
IndentationError と TabError
IDLEでは上記のようにインデントのエラーもSyntaxError
でまとめて表示されましたが、コマンドプロンプトなどの他の環境ではIndentationError
かTabError
で表示されることがあります。どちらも、SyntaxError
の一種です(サブクラスといいます)。
NameError
使用した名前が見つからない例外で出力されます。以下の例では、定義していない変数名(my_data
)を用いているためにエラーが表示されます。
>>> my_data + 5
Traceback (most recent call last): File "<pyshell#0>", line 1, in
my_data + 5 NameError: name 'my_data' is not defined
TypeError
誤ったデータ型どうしの演算や関数の引数に不適切なデータ型を渡した例外で表示されます。以下の例は、文字列型(str
)と整数型(int
)では加法演算(+
)できないのでエラーが表示されます。
>>> "1" + 3
Traceback (most recent call last): File "<pyshell#0>", line 1, in
"1" + 3 TypeError: can only concatenate str (not "int") to str
以下の例では、int()
関数に不適切なデータ型の引数(ここではリスト型)を渡しているためにエラーが表示されています。
>>> int([1,2])
Traceback (most recent call last): File "<pyshell#0>", line 1, in
"1" + 3 TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
ValueError
関数の引数に不適切な値を渡した例外で表示されます。以下の例では、int()
関数に渡した"ichi"
は「10進数の数字」ではないためエラーが表示されています。
>>> int("ichi")
Traceback (most recent call last): File "<pyshell#0>", line 1, in
my_data + 5 ValueError: invalid literal for int() with base 10: 'ichi'
TypeError
は関数に不適切な「型」を、ValueError
は不適切な「値」を渡した時に表示されます。両者の違いに気をつけてください。
IndexError
リスト、タプル、文字列のように、インデックス番号で要素を取り出せるデータで、範囲外のインデックス番号を指定した例外で表示されます。以下の例では、0〜1
の範囲外を指定するとエラーが表示されます。
>>> fruits = ["Apple","Orage","Mango"] >>> fruits[3]
Traceback (most recent call last): File "<pyshell#0>", line 1, in
fruits[3] IndexError: list index out of range
KeyError
辞書で登録されていないキーを指定した例外で表示されます。以下の例では、"country"
はprofile
に登録されていないキーのためエラーが表示されます。
>>> profile = {"name":"Taro Yamada", "city":"Tokyo"} >>> profile["country"]
Traceback (most recent call last): File "<pyshell#0>", line 1, in
profile["country"] KeyError: 'country'
ModuleNotFoundError
import
文で指定したモジュールが見当たらない例外で表示されます。以下の例では、存在しないhoge
モジュールを指定しているためエラーが表示されます。
>>> import hoge
Traceback (most recent call last): File "<pyshell#0>", line 1, in
import hoge ModuleNotFoundError: No module named 'hoge'
pipでインストールしたはずのモジュールが見当たらない場合は、以下のpip list
で実際にインストールされているか確認してください。インストールされていない場合は、再度インストール作業を行います。
C:¥> py -m pip list
# 他のコマンド例(環境により異なります)
$ python3 -m pip list
FileNotFoundError
指定したファイルやディレクトリが存在しない例外で表示されます。以下の例では、fogefoge.txt
というファイルは存在しないのでエラーが表示されています。
>>> stream = open("fogefoge.txt")
Traceback (most recent call last): File "<pyshell#0>", line 1, in
stream = open("fogefoge.txt") FileNotFoundError: [Errno 2] No such file or directory: 'fogefoge.txt'
UnicodeDecodeError / UnicodeEncodeError
書き込みに使用されたのと異なるエンコードで、復号(デコード)しようとすると、UnicodeDecodeError
が発生します。以下の例では、utf-8
で書き込まれたファイル(test.txt
)を、Shift_JIS(cp932
)で読み込もうとしているためにエラーが表示されます。
>>> import os >>> os.chdir("C:/Users/Taro/Documents") >>> with open("test.txt", mode="w", encoding="utf-8") as f: f.write("これはテストです。") 9 >>> with open("test.txt", encoding="cp932") as f: f.read()
Traceback (most recent call last): File "
", line 2, in f.read() UnicodeDecodeError: 'cp932' codec can't decode byte 0x86 in position 11: illegal multibyte sequence
一方、書き込む時に符号化(エンコード)できない文字があると、UnicodeEncodeError
が発生します。以下の例では、半角英数字を表すascii
コードで、全角文字を書き込もうとしているためにエラーが表示されます。
>>> with open("test.txt", mode="w", encoding="ascii") as f: f.write("これはテストです。")
Traceback (most recent call last): File "
", line 2, in f.write("これはテストです。") UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-8: ordinal not in range(128)