IT・技術研修ならCTC教育サービス

サイト内検索 企業情報 サイトマップ

研修コース検索

コラム

ゼロから歩くPythonの道

CTC 教育サービス

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  Microsoft Azure  Docker  Kubernetes 

第41回 Pythonでエラー発生!トレースバックの読み方の基本を学んでみた。 (菱沼佑香) 2023年7月

こんにちは、吉政創成 菱沼です。
今回も「きれいなPythonプログラミング(マイナビ出版)」という書籍を利用して学習します。
こちらの書籍は誰にでも読みやすいコードを書けるようになることを目的とされている書籍のため、以前学習したものも改めて学びなおす場面もあるかと思います。引き続き、超初心者の方にお付き合いいただけましたら幸いです。

さて前回に引き続き、1章エラーメッセージの読み方を学習していきます。
前回はエラーメッセージの基本の部分を、以前学習したときのことを振り返りつつ学習しました。今回はトレースバックの検証について学習したいと思います。

エラー箇所を見つけるトレースバックって何?

さて、前回、構文エラーと例外について再確認しました。
今回学習するトレースバックとは、例外が発生したときに出てくるエラー文の一部分を指すようです。

引用------------------------------------------------
P.4
Pythonのプログラムは、except文で処理できない例外が発生したときにクラッシュします。例外が発生すると、例外のメッセージとトレースバックが表示されるようになっています。トレースバックはスタックトレースとも呼ばれていて、プログラムのどこで例外が発生したのかということと、それまでにどんな関数が呼び出されたのかという履歴が表示されます。
------------------------------------------------------

以下が書籍に書かれていた例外が発生するように記述されたサンプルコード(左)と、実行結果(右)です。(IDLEではTraceback以降のエラーメッセージは赤字で表示されます。)

fig01

このプログラムではdef文を利用して、a、b、cという関数を作っており、それぞれ以下の処理が定義されています。
関数a:①「a()を開始」という文言を表示、②関数bを実行
関数b:①「b()を開始」という文言を表示、②関数cを実行
関数c:①「c()を開始」という文言を表示、②「42÷0」を計算

最後の行(13行目)で関数aが呼び出されていますので、bとcは自動的に実行されることになります。
(def文の使用方法については以前学習したときの記事もぜひご参照ください。)

Pythonのトレースバックの読み解き方

さて、このプログラムで出たエラーメッセージの意味がテキストで解説(P.5)されていますが、そのまま引用すると長くなってしまうのでかいつまんでみたいと思います。(一部そのまま引用します。)

fig02

ここがトレースバックの始まりです。この後に、クラッシュに至るまでの間に呼び出された関数の履歴が、順番に表示されます。それはフレームサマリーといわれるそうなのですが、ここには、フレームオブジェクト(※引用参照)の情報が示されているそうです。

引用------------------------------------------------
P.5 ※フレームオブジェクトについて
関数が呼び出されると、ローカル変数のデータや関数を呼び出した後のコードがどこに戻るかという情報が格納されます。フレームオブジェクトは関数呼び出しに関連するローカル変数やその他のデータを保持するもので、関数が呼び出されるときに生成され、関数が戻ると破棄されます。
------------------------------------------------------

さて、このケースでは4つのフレームサマリーと、最終行にエラーメッセージが表示されています。

fig03

各フレームサマリーに示されている行番号からどの行を実行した履歴なのかわかるようになっており、最終的にエラーを検出した場所がこの中のどこかにあることが示されているそうです。
一番上にあるフレームサマリーには<module>という文字と、プログラムの13行目にある[a()]が表示されています。このことから13行目のプログラムがグローバルスコープであることがわかるのだそう。
(グローバルスコープについては以前の記事もぜひご参照ください。)

このケースで発生しているエラーの内容は[ZeroDivisionError]ですが、これは[c()]の中で設定されている[42/0]が原因となっています。ただ、プログラムの13行目で実行されているのは[a()]で、[c()]は直接には実行されておらず、[c()]は[a()]によって実行される[b()]によって実行されているため、[a()]と[b()]も、エラーがある[c()]を実行するまでに至る経緯の中で実行されているということで、エラーの履歴に含まれているということになるようです。

Pythonのトレースバックで示された箇所と実際の問題個所は別のことがある!?

ところで、学習を始めたばかりの頃、「エラーメッセージが出てもどこを見たらいいのかよくわからない」と質問させて頂いたことがあります。その際、構文エラーに関してはエラーが発生している箇所とは別の行(特に次の行に多いようですが)にマークされることがあると聞いたことがあります。
そういわれてから注意して読んでみると、確かに構文エラーの場合は次の行にマークされることが多いことに気づきました。
たとえばこちら。上がVS Code(黒背景)、下がIDLE(白背景)です。

fig04

fig05

この図でのエラーは「)」で閉じていないことによるものですが、確かにエラーがある行の次の先頭の文字にマークされています。
伺った当時はそんなものかーとその理由を特に気にしなかったのですが、そういわれてみればなぜこうしたエラーの表示になるのでしょうか。テキストでは次のように書かれています。

引用------------------------------------------------
P.7
これは、Pythonのインタープリターが2行目を読むまで構文エラー(SyntaxError)に気づかなかったからです。
------------------------------------------------------

確かに「)」がないというだけでは2行目にその続きがある可能性もありますものね...。
では「)」で閉じられているけど、「"」で閉じられていない場合はどうなるのでしょうか。それがこちら。上がVS Code(黒背景)、下がIDLE(白背景)です。

fig06

fig07

この場合はエラーがあった行にマークされているようです。

トレースバックを読み解くときの注意点

Pythonはバージョン3.10以降から、エラーメッセージをより丁寧でわかりやすいものに変えていこうという流れがあるのだそうです。今後よりわかりやすくなっていけばバグの把握をすばやくできるようになりそうなので、プログラミング初心者にとってはとても嬉しい流れですね。

では最後にトレースバックに関する注意事項について、書籍から転記して今回は終了にしたいと思います。

引用------------------------------------------------
P.7
トレースバックはどこで問題が起こったのかを示してくれますが、それが実際のバグの原因であるかというと必ずしもそうではないのです。フレームサマリーではバグの把握に十分な情報が得られない場合や、トレースバックでは表示されていない部分よりもっと前の行にバグの原因がある場合、デバッガーでプログラムをステップ実行するか、ログメッセージをチェックするなどして原因を探らなければなりません。
------------------------------------------------------

本格的なプログラミングに入れば、たった数行のプログラムという事は少なくなり、それにともなってエラーメッセージも長文になってくると思いますので、エラーもより複雑になってしまうと思います。デバックしないといけない時にはこれを念頭において作業できるようにしたいと思います。

デバック時のポイントや方法について、Pythonエンジニア育成推進協会の寺田様がコラムを公開されていましたので併せてご紹介します。ぜひご参考に。

作ったPythonプログラムが動かない...効率的なデバッグ方法を学んで品質を高めよう|マイナビニュース

エラーメッセージの解決方法は自身で読み解く以外にインターネットに頼るという手段がありますし、書籍でもおすすめされています。
次回はインターネットを頼って解決する糸口をつかむために必要なことについて学びたいと思います。
それでは今回はこちらで終了です。お付き合いいただきありがとうございました。

 


 

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  Microsoft Azure  Docker  Kubernetes