*この記事は実際にプログラミングを勉強しているけど、コードを書くときに躓いている人向けです。
僕がプログラミング初学者だった時、いつもエラー(Runtime Error)が直せず苦戦していました
今回の記事ではそんな経験から、エラーメッセージの読み方と有名なエラーの治し方の勘所を紹介したいなと思います。
(自称)コードのエラーに世界一苦しんだ人なので、同じようにエラーに苦戦している人には割と参考になると思います。(苦笑)
エラー(Runtime Error)の対処方
Runtime Errorは実行中に止まるエラーのことです。
SyntaxError: invalid syntax
Runtime Errorが起こると、プログラミングの実行中にこんな感じで赤文字のエラーメッセージが出ます。(僕はIDLEを使っているので他の場合はわかりませんが、おそらくこんな感じ。)
さて、こういうエラーメッセージが出たとき、どのようにエラーを直せばいいのか実際にみて行きたいと思います。
>>> num1 = 3
>>> print(num2)
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
print(nums)
NameError: name 'num2' is not defined
僕が実際に対話型のshellで書いたものです。
ちなみに欲しかった アウトプットは 3。print()の中身をnum1ではなく、num2と打ち間違ってしまったという設定
まずチェックすべきはErrorの種類と場所です。
今回は NameError が 一行目の print(num2) という場所で 起こったことが赤のエラー文からわかります。
(もし複数のファイルをimportして使っている場合はFile名も要チェック。importって何?ってなっている人は無視してオッケー)
Name Errorとはプログラムが存在しない変数を使おうとしたときに起こるエラーです。なので、エラーメッセージだけで一行目で定義されていない変数num2をプログラムが使おうとしてエラーが出たことがわかります。
なのでnum2をnum1にすればこのコードが正常に動きます。
有名なエラーの種類
どこを直すかはラインの数がでますから簡単に気づけますが、どのように直すかはエラーメッセージから酌み取る必要があります。全てのエラーを覚えておく必要はありませんが、有名なものは覚えておくと便利です。
SyntaxErrorr プログラムに無効のコード存在しているエラー (=文法のミス)
直すべき場所(エラーの行の文法)
例 ① for i on range(3): ② print("d)
エラーメッセージはそれぞれ
① SyntaxError: invalid syntax
② SyntaxError: EOL while scanning string literal
①は普通の構文ミスです。正しくは、if i in range(3): です
興味深いのは②
SyntaxErrorの後の文字が上の普通のものとは異なります。
このエラーメッセージは処理中特定の文字や記号を出てくるを期待
して実行していたらそれがないまま最後の行にたどり着いた
という意味です EOFはEnd of Line (最後のライン)の略だそうです
今回の特定の記号は ” のことです。
文字列は ”Go to the restroom”のように ” で最初と最後をくくる
必要があります。(' も可) よってインタープリター(コードを解釈し
実行するプログラム)は " を見つけると、もう一度 "を見るまで
はすべて文字列だと思います。
今回の場合print("d)で " で見たにも関わらず、2個目の ” がないまま
コードが終わっています。なのでこのようなエラーメッセージが
出たのです。
よって正しくは print("d")
NameError プログラムが存在しない変数を使おうとしたときに起こるエラー
(=変数の名前のミス)
直すべき場所(エラー行の変数の名前 or 以前の行の変数の名前)
例 先ほど取り上げたので割愛
ちなみにこれが一番直すのが簡単なエラー
もしNameErrorがでたら落ち込まずガッツポーズしましょう。
だって変数の名前をチェックしたらいいだけだから。
TypeError 計算式の記号が間違えているときに起こるエラー
(オブジェクト型のミス)
直すべき場所(計算の記号 or 計算式のオブジェクト型)
例 name = "Ymada" + 3
エラーメッセージはこんな感じ
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
name = "Yamada" + 3
TypeError: can only concatenate str (not "int") to str
*この場合の解決策は3を文字型に変えるか、+を*に変えるか
>>>name = "Yamada" + "3"
Yamada3
>>> name = "Yamada" * 3
YamadaYamadaYamada
ValueError 不適切なvalueが使われて起こるエラー
直すべき場所(エラーの行の組み込み関数)
例)number = int("十二")
エラーメッセージ
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
number = int("十二")
ValueError: invalid literal for int() with base 10: '十二'
*この場合の解決策は漢数字をやめて普通の数字にすること
number = int("12")
12
少し上級編
AttributeError Attribute(属性)が原因で起こるエラー
直すべき場所( . の後)
例)math.sprt(4) *実際はこれより前にimport mathが必要
エラーメッセージ
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
math.sprt(4)
AttributeError: module 'math' has no attribute 'sprt'
mathモジュールはsqrtというAttribute (関数) を持っています。
math,sqrt(4) → 2.0
今回はpとqを間違ってsprt()としたので、そんな関数ねーぞって
AttributeErrorが起きたわけです
もちろん正しい答えは math.sqrt(4) です。
* もしmath ( . の前)を間違えるとどうなると思いますか?
少し考えて見てください。
mat.sqrt(4)
出てくるエラーメッセージはこれです。
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
mat.sqrt(4)
NameError: name 'mat' is not defined
正解はNameErrorでした。
AttributeErrorは . の後のAttributeに関するエラーなので
今回はでません。逆にmatはモジュールの名前ではないので、
インタープレターがこんなモジュールも変数もないぞ!って怒って
NameErrorを出します(多分怒ってないけど)
<一番重要> Runtime Error 対処の勘所
最後にエラーの勘所も紹介します。
ズバリ エラーメッセージ = 直す場所 ではないということです。
エラーはインタープレター(機械)の目線でエラーになったときにエラーが起こります。それはプログラマー(人間)の目線とは異なります。
具体例を出します。
frien_name = "Aya"
print(friend_name)
このコードは友達の名前を変数(friend_name)に入れて表示するというものですが、最初の変数を定義するとき、friendのスペルを間違えています。人間の目線では
直すべき場所は最初のラインですが、実際実行すると2行目にNameErrorがでます。
なぜならインタープレターはfrien_nameという変数が定義されてるなー。ん?次の文にfriend_nameという変数名が書いてあるけどそんな変数今までに定義されてないぞ!
よし、NameErrorを出そうって考えるからです。
(もしインタープレターの意味がわからなかったらコンピューターに置き換えてオッケー。)
print(Aya)
このコードはAyaと表示させるために書いたものですが、""でくくるのを忘れています。こんな時Syntaxエラーが怒ってほしいものですが、実際に起こるのはNameErrorです。何でだって? ””で結んでいないものは、(数字を除いて)変数の名前というルールだから、機械の目線ではそんな変数の名前聞いたことないよとしか考えれないからだよ。
food = "onion"
food_price = 70
fruit = "banana"
fruit_price = 40
total_price = (5 * food + 4 * fruit) *1.08
5つの food(玉ねぎ)と 4つの fruit (バナナ)を買ったときの消費税込みの合計金額を表示するコードを書きました。間違いに気づけましたか?
最後の行に値段の入った変数ではなく、食べ物の名前の入った変数で計算しています。
数字ではなく文字列で小数点以下の掛け算が行われたので、TypeErrorがでます。
TypeError: can't multiply sequence by non-int of type 'float'
お気持ちわかります。変数の名前を間違ったのだからNameErrorがでてほしいと思っているんですよね。僕もそう思います。
でも、インタープレター君は素直なんです。最後の計算式を見たとき「food, fruitって変数さっき見たことあるなー。なになに、"onion"と”banana"か。んじゃそれ代入っと」って計算してしまうんです。
これがRuntime Errorの勘所です。
要は機械の目線に(あるいは論理的に)見てあげないと、ただエラーメッセージのエラーの種類や出た行を直せばいいという訳ではないのです。
一応何個かサイトを見たり、教科書で調べたり、自分でコード書いてテストしたりしていますけど、大学生の趣味に毛が生えたレベルのブログなので、間違っている箇所がございましたら怒らず、コメント欄で教えていただけると助かります。
少しでも皆さんのプログラミングの勉強が楽になってくれたら幸いです。