【Python】エラーメッセージの内容を理解する

8 min read読了の目安(約7700字

背景

自身がPython習得をすすめる上での備忘録ではありますが、エラーメッセージの読み解き方を、ここにまとめておきます。

先人たちの知恵をお借りするなどして解決できたことを、この場をお借りして感謝するとともに、大変恐縮ですが 自分のメモ としても、こちらへまとめておきます。

開発環境

  • Windows 10 Pro
  • Python 3.9.0, 3.8.5
  • Django 3.1.3
  • PostgreSQL 13.1
  • Nginx 1.19.5
  • Gunicorn
  • Putty 0.74

エラーメッセージ

1. NameError

1-1.

  • ミス・タイピングによって起こる。大文字・小文字の違いでも起こる。
python
prlnt("Hello World !")    # 誤...print→prlnt

print("Hello World !")    # 正
Traceback (most resent call last):
    file "c:/~/sample.py", line 1, in <module>
        prlnt("Hello World !")
NameError: name 'Prlnt' is not defined

【訳】
直近の最後の呼び出しにおけるモジュール内での名前エラーが発生:1行目の「pilnt」という名前は定義されていません。
 ↓
**『スペルミスをしてるよ~!』**ということ。

1-2.

  • 関数の呼び出しが、関数定義よりも前で行われている場合に起こる。
python
print(cost(100000))        # 誤...costを定義よりも前で、呼び出している

def cost(bill):
    return int(bill * 1.1)
NameError: name 'cost' id not defined

【訳】
NameErrorが発生:「cost」は定義されていません。
 ↓
**『「cost」という関数は、まだ把握・理解していないよ~』**ということ。

2. SyntaxError

  • 文法に関するミスで起こる。

2-1.

python
print("Hello World !)     # 誤...閉じクォート忘れ

print("Hello World !")    # 正
SyntaxError: EOL while scaning stringliteral

【訳】
SyntaxErrorが発生:文字列リテラルの走査中に行末(End Of Line)を見付けました。
 ↓
**『文字列だと思ってたのに、行末になっちゃったけど!?大丈夫?』**ということ。

2-2.

python
print( Hello World ! )    # 誤...クォート忘れ

print("Hello World !")    # 正
SyntaxError: invalid character in identifier

【訳】
SyntaxErrorが発生:識別子の中に不正な文字を見付けました。
 ↓
**『(クォートで囲んでないから)変数か、関数だろうと思ったけど、「!」って使っちゃダメ~』**ということ。

<注>
「!」(エクスクラメーション・マーク)は、変数や関数の名前として使えない文字です。このために不正な文字と指摘されています。

2-3.

python
ifheight > 180:     # 誤...ifの直後に半角スペースが無い

if height > 180:    # 正
SyntaxError: invalid systax

【訳】
SyntaxErrorが発生:不正な文法です。
 ↓
**『そんな書き方じゃダメで~す』**ということ。

3. TypeError

  • データの型に問題があるときに起こる。
python
print(5 + "枚")        # 誤...5(数値)と、"枚"(文字列)を、+演算子で結合しようとしたが、方が異なるため連結できない

print("5" + "枚")      # 正...型をstr型に合わせる
print(str(5) + "枚")   # 正...同上
TypeError: unsupported operand type(s) for +: 'int' and 'str'

【訳】
TypeErrorが発生:+演算子は被演算子の型を支持していません。
 ↓
**『データの型が、intとstrとで異なるから一緒に処理できないよ~』**ということ。

4. IndentaionError

  • ifやfor文、関数などのネストのインデントが無かったり、ズレていたりすると起こる。
python
if counter > 10:
break               # 誤...インデントが無い

if counter > 10:
    break           # 正
IndentationError: expected an indented block

【訳】
IndentationErrorが発生:インデントされたブロックが必要だと予測します。
 ↓
**『インデントしていないけど、インデントが必要だよねぇ~』**ということ。

※逆の場合(インデントが不要なのに、インデントしている場合)も、同様にIndentationErrorとなります。

5. ValueError

  • 演算子や関数が、正しい型だが適切でない値を持つ引数を受け取ったときや、 IndexError のような、より詳細な例外では記述できない状況で起こる。
python
print(int('xxxxxxx'))
ValueError: invalid literal for int() with base 10: 'xxxxxxx'

【訳】
ValueError:引数baseが10であるint関数に対して、不正なリテラル:文字列「xxxxxxx」です。
 ↓
**『10進数に変換できない「xxxxxxx」という文字列を入れてますよ~!』**ということ。

※int関数は、第二引数に、baseという引数を指定することが可能。引数baseは基数を表します。省略した場合はデフォルト値:10が与えられます。
 「with base 10」=『基数を10に指定(=10進数へ変換する)』ことを表します。

6. ModuleNotFoundError

  • モジュールをimportできない場合に起こる。(主にタイプ・ミスによる)
python
import xxxxxxxx
ModuleNotFoundError: No module named 'xxxxxxxx'    # 「xxxxxxxx」というモジュール名が見付からない

【訳】
モジュールが見付からないエラーが発生:「xxxxxxxx」という名前のモジュールがありません。
 ↓
**『「xxxxxxxx」って名前のモジュールなんて、ありまへんっ!』**ということ。

7. ZeroDivisionError

  • いわゆる「ゼロ割り」した場合に起こる
python
10 + 10 + 10 + 10 * 0 + 10 + 10 / 0 + 10
ZeroDivisionError: division by zero

【訳】
ZeroDivisionErrorが発生:ゼロで割り算しました。
 ↓
(そのまま)**『ゼロ割りじゃん!』**ということ。

8. KeyboardInterrupt

  • 実行中に割り込みキー(「ctrl」+「C」キー等)を押下すると起こる。(無限ループを止める際等)
Traceback (most resent call last):
    file "c:/~/sample.py", line 120, in <module>
        counter += 1
KeyboardInterruput

【訳】
キーボードからの割り込みが入りました。
 ↓
**『キーボードから割り込みキーが入力されたよ!』**ということ。

9. ImportError

  • from <モジュール名> import <オブジェクト名、関数名 など)> でモジュールに含まれていないオブジェクトをインポートしようとした場合などに発生する。大文字・小文字も区別されるため、タイプミスに注意。
python
from bs4 import BeautifulSoap    # 誤...Soap→Soup

from bs4 import BeautifulSoup    # 正
ImportError: cannot import name 'BeautifulSoap' from 'bs4' (/usr/local/~/python/3.9.0/・・・)

【訳】
import(取り込み)Errorが発生:「bs4」から「BeautifulSoap」という名前のモジュールを取り込めません。
 ↓
**『「BeautifulSoap」って名前のモジュールが取り込めないよ~!』**ということ。

※綺麗な石鹸(Soap)じゃなくて、<font color="orange"><b>美味しいスープ(Soup)</b></font>ですよ~!^^

<注>
モジュール名やオブジェクト名は正しいか、対象のモジュールにそのオブジェクトが含まれているかは、公式ドキュメントなどを確認する癖を付けましょう
稀にライブラリがバージョンアップされた際に、そのオブジェクト名が変わったり、無くなったり(廃止されたり)します

10. IndexError

  • リストやタプルなどシーケンスオブジェクトに格納された値を [インデックス] で取得する際、その範囲外の位置(要素数を超えたインデックス値)を指定することで起こる。
python
list1 = ["あ", "い", "う", "え", "お"]

print(list1[5])        # 誤...末尾の "お" は、インデックスでは [要素数-1] であるため、4 と指定するのが正解

print(list1[4])        # 正
# お
IndexError: list index out of range

【訳】
IndexErrorが発生:リストの索引は範囲外です。
 ↓
『リスト型の索引の範囲外だよ~(...だから探しに行けないの...)**』**ということ。

リストやタプルの要素数は len() 関数で確認可能です。よく確認してからインデックスを指定しましょう。
ちなみに、インデックスは 0 から数えはじめますので、末尾は 要素数-1 番目になります。

python
list1 = ["あ", "い", "う", "え", "お"]

print(len(list1))
# 5

11. KeyError

  • 辞書型(dict型)の値をキー指定して取得する際、存在しないキーを指定してしまうと起こる。
python
dict1 = {1 : "りんご" , 2 : "みかん", 3 : "ぶどう" , 4 : "バナナ"}

print(dict1[5])    # 誤...'5' は、Key として存在しない

print(dict1[4])    # 正
# バナナ
KeyError: 5

【訳】
KeyErrorが発生:'5'(が、キーエラーです。)
 ↓
(そのまま)**『5 は キーエラーですな~』**ということ。

キーの一覧は、keys() メソッドで確認しましょう。

python
dict1 = {1 : "りんご" , 2 : "みかん", 3 : "ぶどう" , 4 : "バナナ"}

print(dict1)
# {1: 'りんご', 2: 'みかん', 3: 'ぶどう', 4: 'バナナ'}

print(list(dict1.keys()))
# [1, 2, 3, 4]

裏技?
get() メソッドを使うと、存在しないキーに対してもエラーになりません。
この場合、デフォルト値を取得することができます!

python
print(dict1.get[5])

# None

辞書に含まれるキーや、指定したキーが正しいかを、よく確認しましょう。
(指差し確認、安全よーし!!)

12. AttributeError

  • 属性(Attribute)の参照に関して起こる。

「<オブジェクト>.<識別子>」のようにメソッドなどを呼び出す際、オブジェクトや識別子(属性やメソッド)の名前、オブジェクトの型を間違えた場合に発生する。
大文字・小文字も区別されるため、タイプミスに注意。

12-1.

  • 識別子の名前を間違えた例:
python
import math

print(math.PI)        # 誤...PI→pi

print(math.pi)        # 正
AttributeError: module 'math' has no attribute 'PI'

【訳】
AttributeErrorが発生:'math' モジュールは 'PI' という属性を持ち合わせません。
 ↓
**『「math」は「PI」なんて、持ってないってさ!』**ということ。

12-2.

  • オブジェクトの型が想定と違った例:
python
counter = 60

counter.append(120)
AttributeError: 'int' object has no attribute 'append'

【訳】
AttributeErrorが発生:'int' オブジェクト(数値型オブジェクト)は 'append' という属性を持ち合わせません。
 ↓
**『数値型オブジェクトに「append」なんて、備わってないってよ~』**ということ。

オブジェクト名、識別子名や、オブジェクトの型は想定通りか、をよく確認しましょう。

13. FileNotFoundError

  • ファイルを読み込む際など open() で指定したファイルが見つからないときに起こる。
python
with open('sample1.txt') as f:    # sample1.txt は存在しない
    print(f.read())
FileNotFoundError: [Errno 2] No such file or directory: 'sample1.txt'

【訳】
FileNotFoundErrorが発生:'sample1.txt' というファイルまたはディレクトリはありません。
 ↓
**『「sample1.txt」 は ありまへんがな~』**ということ。

指定したファイルやディレクトリは本当に存在している?
指定したパスは正しい?特に、相対パスで指定したときのカレントディレクトリは正しい?
(相対パスで指定した際、Pythonのカレントディレクトリが想定と異なっている可能性も考えられます。)

14. FileExistsError

  • ファイルやディレクトリを作成しようとした際に、それが既に存在したときに起こる。(13.の逆パターン)
python
import os
os.mkdir('sub_dir')        # 'sub_dir' は既に存在している
FileExistsError: [Errno 17] File exists: 'sub_dir'

【訳】
FileExistsErrorが発生:'sub_dir' というファイル(またはディレクトリ)は存在します。
 ↓
**『「sub_dir」 は もう在るやん!』**ということ。

指定したファイル(またはディレクトリ)はすでに存在していない?

<注>
python 3.2.x 以降では、os.makedirs() に引数 exist_ok が追加されています。
このため、exist_ok=True とした際には、既に存在しているディレクトリの作成を試みてもエラーとなりません。


(編集後記)

よく遭遇するエラーを集めてまとめてみました、の第二弾です。
エラーの内容、原因・理由を理解して、複雑なプログラミングをする際に、エラーが出ても慌てないようすることと、対処を適切に素早く施せるようにしたいですね。

VS Code には、リアルタイムに文法をチェックしてくれる拡張機能もあるようですので、VS Code をお使いの方は、いろいろ試してみてください。