プログラムにクォートの閉じ忘れのような「構文エラーSyntaxError)」があるとPythonはすぐさまエラーを表示します。構文エラーを修正し、無事プログラムを実行できても、予想外のデータが入力されたりすると今度は「例外Exception)」発生をエラーで通知します。

例外とはまさしくプログラム実行時の「例外」です。例えば、文字列を入力すべき箇所に数値が入力された、読み込むファイルがない、などの「例外」が検知されるとエラーで教えてくれます。

このようにPythonでは構文エラー例外発生時エラーを表示します。エラーの対策は必須ですが、その前にまず原因を把握する必要があります。Pythonプログラミング通信講座のなかでも適時説明していますが、今回「見方とよくあるエラー」をまとめましたので、参考にしてください。

構文エラー、例外、バグは区別してください

構文エラーがあるとプログラムを実行できません。プログラムを実行できても、処理できないデータの入力など例外が検知されるとエラーを表示します。バグとは、「プログラム中の誤り」全般のことですが、ロジックの間違いに起因する場合は、ほとんど例外では検出できないので、こちらの方が対策が難しくなります。

エラーと例外(Python公式ドキュメント)

エラーの見方

IDLEでPythonファイルを実行した場合、エラーは以下のように表示されます。

◯「構文エラー」の場合

プログラムに構文の間違えがあると、以下のように構文エラーSyntaxError)をダイアログで表示します。同時に該当箇所を赤いハイライトで示してくれます。

syntax error

IDLEではメッセージがダイアログで表示されます。

この例では「EOL while scanning string literal(文字列の値をスキャンしているうちに行末まで来てしまいました)」と表示されています。これから、行内にクォートがあるのに、行末(EOL:End Of Line)までに閉じるクォートを探せなかった、つまりクォートの閉じ忘れが原因であると分かります。

◯「例外」の場合

例外が検知されると以下のように赤い文字でその内容が出力されます。最初にTraceback (most recent call last):と表示されて、最後にエラーの内容が表示されます。

track back

今回の例では、実際に例外が発生しているのはTracebackの最後にあるzipfile.pyの1204行です。このコードを呼び出しているのは、その上のphys_pkg.pyの101行です。このように呼び出し履歴を遡ってゆくと、例外の原因となる自分のコードに辿り着きます。この呼び出し履歴を遡って追跡することを「Traceback」と言います。

ここでは、エラーの内容が「FileNotFoundError: [Errno 2] No such file or directory: ~」と表示されているので、「指定したファイルかディレクトリが見当たらない」ために例外が発生していることが分かります。そして、Tracebackを辿ることで自分のコード(docx_extract_text.py)の8行目が発端になっていることが判明するので、そこをチェックし修正します。

ここでエラー番号([Errno 2])とは、その後に続くメッセージ(No such file or directory)と対応しているので、このエラー番号の意味を別に調べる必要はありません。

よくあるエラー

ここからは、IDLEの対話モード(インタラクティブシェル)を用いて、簡単なコードでよくあるエラーを再現してみます。他のエラーや詳細については以下の公式ドキュメントを参照してください。

Pythonの組み込み例外(Python公式ドキュメント)

よくあるエラーの一覧
  1. SyntaxError
  2. NameError
  3. TypeError
  4. ValueError
  5. IndexError
  6. KeyError
  7. ModuleNotFoundError
  8. FileNotFoundError
  9. 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でまとめて表示されましたが、コマンドプロンプトなどの他の環境ではIndentationErrorTabErrorで表示されることがあります。どちらも、SyntaxErrorの一種です(サブクラスといいます)。

NameError

使用した名前が見つからない例外で出力されます。以下の例では、定義していない変数名(my_data)を用いているためにエラーが表示されます。

>>> my_data + 5Traceback (most recent call last):
  File "<pyshell#0>", line 1, in 
    my_data + 5
NameError: name 'my_data' is not defined

TypeError

誤ったデータ型どうしの演算関数の引数に不適切なデータ型を渡した例外で表示されます。以下の例は、文字列型(str)と整数型(int)では加法演算(+)できないのでエラーが表示されます。

>>> "1" + 3Traceback (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 hogeTraceback (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
ModuleNotFoundErrは、Python3.6から追加されました。前のバージョンでは、ImportErrorが表示されます。

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)