この記事を書くきっかけ
プログラミングの問題を解くときも、Webアプリケーションを作るときも、必ず毎日出会うのがエラーです。エラーが当たり前すぎて、エラーなしに一発でうまく動いたときは逆に「おかしい」と疑ってしまうくらいです。
そんなエラーですが、よく見かける割によく知らないまま、今の今まで過ごしてしまっていることに気づきました。
例えば、突然「SyntaxError」と表示されても、それがどういう場面で出現し、何が原因でエラーになること多いのか、どこに注目すれば解消できるのか、すぐには答えられません。今まで、どのくらいの種類のエラーに出会ったのかもわかりません。
そこで、Pythonのコーディング中によく見かけるエラーを、一度ちゃんと調べてみることにしました。
この記事は下記の形式に則って整理しています。
- エラーの名前
- エラー発生のコード例
- 「発生しやすい状況」(なぜ発生するのか(WHY))
- 「修正ポイント」(どこに注目すれば解消されるのか(HOW TO))
- 自分へ向けたメッセージ
私と同じようなPython初心者の方は、ぜひ参考にしてみてください。
Python公式ドキュメント
1. SyntaxError (構文エラー)
構文が間違っている場合に発生します。
if x == 10 # コロンの忘れ
print("x is 10")
発生しやすい状況
- 条件文やループ文でコロンを忘れたとき
- 括弧の閉じ忘れ
- 文法の書き方を間違えたとき
修正ポイント
- コード全体の構文を確認して、抜けている記号(コロン、括弧など)を補う
- エラーメッセージを参照して、指摘された箇所を修正する
SyntaxErrorは、構文を正しく書けば解消するエラーなので、このエラーが出てもそこまで怖がらなくて大丈夫。落ち着いて正しい構文を書き直す。
2. IndentationError (インデントエラー)
インデントが正しくない場合に発生します。Pythonはインデントによってブロックを区切るため、インデントが揃っていないとエラーになります。
def example():
print("Hello, world!") # インデントが不足している
発生しやすい状況
- 関数やループ内で正しいインデントになっていない
- インデントが混在(タブとスペースの混在)
- 複数行のブロックの中でインデントが統一されていない
修正ポイント
- インデントをするときはスペースまたはタブを使用する
- インデントの深さが正しいか確認し、必要に応じて調整する
IndentationErrorは、正しいインデントにすれば解消するエラーなので、怖がらなくて大丈夫。コード全体を見て正しいインデントになっているかをすぐに確認する。日本語入力のままスペースしてしまっている箇所も当然エラーなので、コードを書くときは変換にも注意する。
3. NameError (名前エラー)
定義されていない変数や関数を参照しようとした場合に発生します。
print(variable) # variableが定義されていない
発生しやすい状況
- 未定義の変数や関数を使用したとき
- スコープの外で変数を使用したとき
- タイプミスによる変数名の間違い
修正ポイント
- 変数や関数が適切に定義されているか確認する
- 変数のスコープが正しいか確認し、必要に応じて適切な位置に変数を移動する
- タイプミスを修正
NameErrorが出現したときは変数や関数に注目する。ローカル変数で定義したものをスコープの外で参照するとこのエラーになる。スコープの中で参照するか、グローバル変数を使えば解消される。タイプミスの場合もよくある。
4. TypeError (型エラー)
データ型が適切でない操作をしようとした場合に発生します。
result = 10 + "5" # 整数と文字列の加算
発生しやすい状況
- 異なる型のデータを操作したとき
- 関数に不適切な型の引数を渡したとき
- リストや辞書のキーとして不適切な型を使用したとき
修正ポイント
- 操作対象のデータ型が正しいか確認する
- 関数やメソッドに渡す引数の型が適切か確認する
- リストや辞書のキーとして適切な型を使用する
TypeErrorは、型に注目する。よくあるのは、int型だと思っていたのに、str型になっていて、四則演算の計算ができないとき。このエラーが出たときは、そのエラー箇所で使われている型が合っているかどうか確かめる。
5. ValueError (値エラー)
関数に渡された引数の値が不適切な場合に発生します。
number = int("abc") # 文字列を整数に変換しようとする
発生しやすい状況
- 不適切な形式のデータを変換したとき
- リストのインデックスに不適切な値を使用したとき
- 不適切な形式のデータを関数に渡したとき
修正ポイント
- データの形式や範囲が適切か確認する
- 変換前にデータの形式を検証する
- 関数に渡す前にデータが適切な形式かどうかを確認する
ValueErrorは値の型に注目する。例えば、int関数に文字列が渡された場合、変換できないのでエラーが返ってくる。
6. IndexError (インデックスエラー)
リストやタプルなどのシーケンスの範囲外のインデックスにアクセスしようとした場合に発生します。
list_example = [1, 2, 3]
print(list_example[5]) # インデックスが範囲外
発生しやすい状況
- リストやタプルの範囲外のインデックスを使用したとき
- 空のリストに対してインデックスを使用したとき
- リストのサイズを超えるインデックスをループで使用したとき
修正ポイント
- インデックスがリストやタプルの範囲内か確認する
- リストやタプルが空でないか確認する
- ループの範囲が正しいか確認する
IndexErrorはIndexError: list index out of range
という形でよく目にする。リストのサイズを確かめる。普通にif文While文のコードの書き方が間違っているときによく出現する。
7. KeyError (キーエラー)
辞書に存在しないキーにアクセスしようとした場合に発生します。
dict_example = {"key1": "value1"}
print(dict_example["key2"]) # 存在しないキーへのアクセス
発生しやすい状況
- 辞書に存在しないキーを使用する
- 辞書のキーのスペルミス
- 辞書に存在するキーが削除された後にアクセスする
修正ポイント
- 辞書のキーが存在するか確認する
- キーのスペルが正しいか確認する
- キーが削除されていないか確認する
KeyErrorの原因は、主にキーのスペルミスまたはキーが存在しない場合の2パターンが多いので、落ち着いて対処する。
8. AttributeError (属性エラー)
オブジェクトに存在しない属性やメソッドにアクセスしようとした場合に発生します。
string_example = "hello"
string_example.append("!") # 文字列オブジェクトにappendメソッドは存在しない
発生しやすい状況
- オブジェクトに存在しないメソッドを呼び出す
- NoneTypeオブジェクトに対して属性を呼び出す(ないものを呼び出す)
- オブジェクトの属性をスペルミス
修正ポイント
- オブジェクトが適切な属性やメソッドを持っているか確認する
- 属性が存在することを確認する
- 属性やメソッドの名前を確認する
AttributeErrorが出現したら、オブジェクトの使い方が正しいかどうかを確認する。単純にスペルミスのことも多い。
9. ImportError (インポートエラー)
モジュールが見つからなかったり、存在しない名前をインポートしようとした場合に発生します。
import non_existent_module # 存在しないモジュールのインポート
発生しやすい状況
- 存在しないモジュールをインポートするとき
- モジュールから存在しない名前をインポートするとき
- モジュールのパスが間違っているとき
修正ポイント
- モジュールや関数が存在するか確認する
- インポートパスが正しいか確認する
- パッケージが適切にインストールされているか確認する
ImportErrorが出た原因でよくあったのは、パッケージがインストールされていないだけだったというもの。コードの書き方にミスがあると思い込んでしまうと発見に時間がかかるので、パッケージがちゃんとインストールされているか早めに確認する。
10. ZeroDivisionError (ゼロ除算エラー)
数値を0で除算しようとした場合に発生します。
result = 10 / 0 # ゼロによる除算
発生しやすい状況
- 明示的なゼロでの除算
- 変数がゼロの場合の除算
- ループや計算の途中でゼロ除算が発生したとき
修正ポイント
- 除算の前にゼロでないことを確認する
- 変数がゼロでないか確認する
- ループや計算の前にゼロチェックを行うする
ZeroDivisionErrorは、今のところあんまり見かけない。ただ、かなり重要なエラーだと聞いているので、今度見かけたらしっかり勉強する。
まとめ
エラーが出たら、焦るし、英語だし、イラっとするし、とにかく嫌な気持ちになるものです。コードを一生懸命たくさん書いても、ほんのちょっとのミスだけで、プログラム全てが動かなくなってしまいます。そんなときは、すべてを投げ出してしまいたくなります。短気!
ただ、今回よく見かけるエラーを調べてみると、「〇〇Error」というような、エラーの名前を見るだけでも解決への手順をある程度絞ることができるとわかりました。
また、この他にもたくさんの〇〇Errorがありますが、その名前を気にしなくても、
- タイプミス
- 型のミス
- 書き方(構文)のミス
これらを確認するだけで、すぐに解決できることもあるとわかりました。それは、この3つのミスはどのエラーにも共通して起こりうるミスだからです。
ほとんど99%は合っているのに、1%のミスで0になってしまう。プログラムとは、「0か100か」「正解か不正解か」で判断される、なんとも厳しい世界です。ただ逆に、その1%を直せば0だったものがすぐ100になってくれます。そう考えると、なんだかお得ですね。
これからは、エラーを極端に恐れずに、エラー =「1%のミスを教えてくれるヒント」だと思って、コーディングに取り組みたいと思います。