プログラムを実行したら、NameError: name 'x' is not defined という英語が出て止まってしまった。そんな経験はありませんか?
Pythonを学び始めたころ、いちばんよく目にするエラーのひとつがこのNameErrorです。見慣れない英語に一瞬ひるみますが、実は原因のパターンがかなり限られている、とても素直なエラーでもあります。
この記事では、NameErrorが出る仕組みから、よくある原因と直し方、最近のPythonが出してくれるヒントの読み方までを順番に見ていきます。サンプルの実行結果は、手元のPython 3.11、3.12、3.13で確認したものです。
NameErrorとはどんなエラーなのか¶
まずは、NameErrorがどんな場面で起きるのかを押さえておきましょう。ひとことで言うと、Pythonがその名前を知らないときに出るエラーです。
Pythonでは、変数や関数、クラス、モジュールにはすべて名前がついています。プログラムの中で名前が出てくると、Pythonはその名前が何を指しているのかを探しにいきます。
探しても見つからなかったとき、Pythonは処理を止めてNameErrorを出します。つまり、NameErrorは、まだ用意されていない名前を使おうとした合図なのです。
ここで大事なのは、NameErrorは文法の間違いではないという点です。文法の間違いならSyntaxErrorになり、プログラムは1行も動きません。NameErrorは、実際にその行まで処理が進んだときに初めて起きます。
エラーメッセージの読み方¶
次に、エラーメッセージのどこを見ればよいのかを確認しましょう。たとえば、変数名を1文字打ち間違えたコードを動かすと、次のような表示になります。
message = "こんにちは"
print(mesage)
実行すると、最後の行に次のメッセージが出ます。
NameError: name 'mesage' is not defined. Did you mean: 'message'?
前半の name 'mesage' is not defined は、mesage という名前は定義されていません、という意味です。引用符の中に、Pythonが見つけられなかった名前がそのまま入っています。
後半の Did you mean: 'message'? は、もしかして message のことですか、という提案です。この一文があるだけで、原因探しがぐっと楽になりますね。
エラー表示全体の読み方は、こちらの記事でくわしく解説しています。どの行で止まったのかは、メッセージの少し上に表示されます。 【関連記事】Pythonのエラー文はどこを読めばいい?初心者向けtracebackの見方
NameErrorのよくある原因と直し方¶
NameErrorの原因は、だいたいいくつかのパターンに分けられます。代表的なものを表にまとめたので、エラーが出たらまずこの中から当てはまるものを探してみてください。
| 原因 | 例 | 直し方 |
|---|---|---|
| 名前の打ち間違い | mesage と message | 正しいつづりに直す |
| 大文字と小文字の違い | true と True | Pythonの決まった書き方に合わせる |
| importを忘れている | import せずに sys.version | ファイルの先頭で import する |
| 定義する前に使っている | 関数を def より上で呼ぶ | 定義を呼び出しより前に置く |
| 文字列の引用符を忘れた | print(hello) | print("hello") とする |
| 別の関数の中の変数を使った | 関数Aの変数を関数Bで使う | 引数や戻り値で受け渡す |
| ifの中でしか作っていない | 条件がFalseで代入されない | 先に初期値を入れておく |
この表の中でも、初心者がとくにつまずきやすいものを、ここから順番にくわしく見ていきます。
打ち間違いと大文字・小文字の違い¶
いちばん多いのは、やはり打ち間違いです。Pythonは大文字と小文字を区別するので、Message と message は別の名前として扱われます。
よくあるのが、真偽値の True を true と書いてしまうケースです。手元のPython 3.11で試すと、Did you mean: 'True'? とちゃんと提案してくれました。
ほかの言語を学んだことがある人ほど、この間違いをしがちです。JavaScriptでは true と小文字で書くので、手がそちらを覚えてしまっているんですね。
文字列の引用符を忘れている¶
意外と見落としやすいのが、文字列を引用符で囲み忘れるケースです。print(hello) と書くと、Pythonは hello を文字列ではなく変数の名前だと受け取ります。
hello という変数はどこにもないので、NameErrorになるわけです。エラーメッセージに出てきた名前が、本当は表示したかった文字そのものだったら、引用符を疑ってみてください。
import忘れと定義の順番に注意¶
続いて、名前は合っているのにNameErrorになるケースを見ていきましょう。代表的なのが、import忘れと、定義の順番の問題です。
importを忘れたときのヒント¶
標準ライブラリのモジュールは、import してから使う決まりになっています。import sys を書かずに sys.version を使うと、NameErrorになります。
ここで、Pythonのバージョンによって表示が変わる点が面白いところです。手元の3.11では name 'sys' is not defined だけでしたが、3.12と3.13では Did you forget to import 'sys'? というヒントが加わりました。
これはPython 3.12の新機能で、公式のWhat's Newでも、標準ライブラリのモジュール名が提案されるようになったと紹介されています。import忘れだとすぐにわかるので、学習中の人にはうれしい改善ですね。
なお、pip で入れた外部ライブラリが見つからない場合は、NameErrorではなくModuleNotFoundErrorになります。こちらは import の行そのもので起きるエラーなので、原因と対処が違います。 【関連記事】PythonのModuleNotFoundErrorって何?解決するにはどうしたらいいの?
関数を定義する前に呼んでいる¶
Pythonは、ファイルを上から順番に実行していきます。そのため、def で関数を定義するより前の行で呼び出すと、その時点ではまだ名前が存在しません。
次のコードで、どこでエラーになるかを確かめてみましょう。
def greet():
print("hi")
greet() # これは動く
hello() # ここでNameError
def hello():
print("hello")
greet() は定義のあとに呼んでいるので問題なく動きます。一方の hello() は、定義が下にあるのでNameErrorになります。
ちなみに、このとき手元の3.12では Did you mean: 'help'? と提案されました。help は組み込み関数なので、つづりが近い名前として選ばれたのでしょう。Did you mean はあくまで推測なので、提案をうのみにせず、本当にその名前を使いたかったのかを自分で確かめることが大切です。
スコープが原因のNameError¶
ここからは、少しレベルが上がります。名前のつづりも順番も正しいのに、それでもNameErrorになることがあるのです。
その原因の多くは、スコープと呼ばれる名前の有効範囲にあります。関数の中で作った変数は、その関数の中でしか使えません。
たとえば、関数 calc の中で result という変数を作り、別の関数 show から result を使おうとすると、NameErrorになります。show から見ると、result はどこにも存在しないからです。
このようなときは、calc から return で値を返し、show に引数として渡すのが基本の直し方です。名前の有効範囲の考え方は、こちらの記事でくわしく解説しています。 【関連記事】Pythonの名前空間を理解するとコードがスッキリ!初心者にもわかりやすく解説
クラスの中でselfを付け忘れる¶
クラスを書き始めた人がよくつまずくのが、self の付け忘れです。init で self.total = 0 としておきながら、別のメソッドで print(total) と書いてしまうパターンですね。
total と self.total は、Pythonにとってまったく別の名前です。そのため、print(total) の行でNameErrorになります。
うれしいことに、Python 3.12以降では、この場合に Did you mean: 'self.total'? と提案してくれます。手元の3.11では提案がなく、3.12と3.13では表示されることを確認できました。
UnboundLocalErrorはNameErrorの仲間¶
NameErrorとよく似たエラーに、UnboundLocalErrorがあります。どんな関係なのか、気になりますよね。
実はUnboundLocalErrorは、NameErrorを親に持つ子どものクラスです。issubclass(UnboundLocalError, NameError) を実行すると、True が返ってきます。
このエラーは、関数の中のローカル変数を、値を入れる前に使おうとしたときに起きます。次のコードは、条件によっては変数が作られないパターンです。
def judge(score):
if score >= 60:
result = "合格"
print(result)
judge(80) # 合格
judge(40) # UnboundLocalError
score が60以上なら result に値が入りますが、40のときは代入が一度も行われません。Pythonは result をこの関数のローカル変数だと判断しているので、値がないまま読もうとしてエラーになるのです。
手元の3.11以降では、cannot access local variable 'result' where it is not associated with a value というメッセージになりました。直し方は、if の前で result = "不合格" のように初期値を入れておくことです。
関数の外の変数を書き換えようとして起きるUnboundLocalErrorについては、こちらの記事でくわしく解説しています。 【関連記事】Pythonのglobalとnonlocalとは?関数の中から外の変数を書き換える方法と、UnboundLocalErrorが出る理由
NameErrorをtryで受け止める前に考えたいこと¶
NameErrorも例外の一種なので、try と except で受け止めることはできます。except NameError as e と書けば、e.name でPythonが見つけられなかった名前を取り出せます。
試しに、存在しない score を使うコードを try で囲んでみましょう。
try:
print(score)
except NameError as e:
print(type(e).__name__) # NameError
print(e) # name 'score' is not defined
print(e.name) # score
ひとつ面白いのは、print(e) で表示したメッセージには Did you mean の部分が含まれないことです。手元で確かめたところ、提案はエラーがそのまま画面に表示されるときにだけ付け足されていました。
ただし、NameErrorを try で握りつぶすのは、ほとんどの場合おすすめしません。NameErrorは、ネットワークの不調のような外の事情ではなく、コードそのものの書き間違いで起きるエラーだからです。エラーを隠すのではなく、原因になった行を直すのが正解です。
例外処理の基本的な使い方は、こちらの記事でまとめています。 【関連記事】Pythonのtry・except・else・finallyとは?例外処理の基本の流れ
実務でNameErrorに泣かされた話¶
ここで、私自身の失敗談をひとつ紹介させてください。私は10年ほどエンジニアとして開発に関わってきましたが、本番環境でNameErrorを出してしまったことがあります。
原因は、めったに通らないエラー処理の分岐の中で、変数名を1文字打ち間違えていたことでした。ふだんの動作確認ではその分岐を一度も通らなかったので、誰も気づかないまま公開されてしまったのです。
NameErrorは、その行が実行されるまで見つからないという性質があります。だからこそ、めったに通らない分岐ほど、テストで一度は通しておくことが大切だと痛感しました。
それ以来、私はRuffのような静的解析ツールを使うようにしています。コードを実行しなくても、定義されていない名前を見つけてくれるので、こうした事故をかなり防げます。
NameErrorを未然に防ぐ習慣¶
最後に、NameErrorを減らすための習慣を紹介します。どれも今日から始められるものばかりです。
ひとつ目は、エディタの補完機能を積極的に使うことです。VS Codeなどのエディタでは、変数名の途中まで打つと候補が出てくるので、打ち間違いそのものが起きにくくなります。
ふたつ目は、エディタに表示される波線を見逃さないことです。定義されていない名前には、実行する前から警告の印が付くことがよくあります。
みっつ目は、import はファイルの先頭にまとめて書くことです。使う場所の近くでばらばらに書くと、どこかで書き忘れたり、条件によって実行されなかったりします。
そして、エラーが出たら慌てずに、メッセージの引用符の中にある名前を確認しましょう。その名前がどこで作られているはずなのかを考えると、たいていはすぐに原因が見つかります。
まとめ¶
今回は、PythonのNameErrorについて解説しました。最後に要点を振り返っておきましょう。
NameErrorは、Pythonがその名前を見つけられなかったときに出るエラーです。原因の多くは、打ち間違い、import忘れ、定義の順番、スコープ、条件によって代入されない変数のどれかに当てはまります。
Python 3.10以降の Did you mean や、3.12から加わった import忘れや self のヒントは、原因探しの心強い味方です。ただし提案は推測なので、最後は自分の目で確かめてください。
NameErrorは怖いエラーではなく、名前のどこかがずれていると教えてくれる親切なエラーです。メッセージを落ち着いて読む習慣をつければ、きっとすぐに直せるようになりますよ。
ここまでお読みいただきありがとうございました。