Pythonでコードを書いていると例外処理を行いたい事があります。
エラーの内容は基本的には実行時にエラーチェックをしてくれます。それに機能的な事前に一覧化してエラーコードの一覧などを作るのが一般的です。
しかし、例えば、ネットワークに関するエラー(特にAPIなどで外部のサーバにリクエストする場合)に関してはどの様なエラーが返ってくるか全く分かりません。そんな時は「try-except」を使って例外処理のコードを書くのが一般的です。
今回はPythonで例外処理をする際に使う「try-except」について解説します。
コンテンツ
エラーについて知っておこう!
まずはPythonのエラーの種類について、ざっくりとおさらいしておきましょう。
Pythonの公式チュートリアルでも紹介されていますが、エラーには以下の2種類があります。
・構文エラー(SyntaxError)
・例外
まずはこの2つのエラー(とおまけ)についてご紹介します。
構文エラー(SyntaxError)
構文エラーというのは簡単に言うとコードの書き方が間違っている場合に発生するエラーとなります。Pythonを使用されているのであれば、おそらくこのエラーは何度も見た事があると思います。
例として、datetimeモジュールを使った以下の様なコードを実行してみましょう。
■Pythonコード
1 2 |
nowDT = datetime.now() print(nowDT) |
■実行結果
1 2 3 4 |
Traceback (most recent call last): File "Main.py", line 3, in <module> nowDT = datetime.now() NameError: name 'datetime' is not defined |
■解説(簡単な)
このコードだとエラーが発生してしまいましたね。それもそのはず、datetimeモジュールを使っているのに、importができていません。
先頭に「from datetime import datetime」の様にインポート文を書いてあげればエラーは解消します。
例外
構文エラーに対して例外のエラーも存在します。昔からプログラミングをされている方であれば、分かりやすいのは0で割り算(5/0の様に)してしまった場合に発生するエラーが有名です。
コードを書いている時点ではこのエラーに気づかず、実際に処理を動かしてみたら「x/yという割り算をする際のyの値が0になってた。」なんて事は結構あります。C言語では特にあったな。。。
また、冒頭でもお伝えした様に外部のサーバなどにリクエストした場合は、どの様な値が帰ってくるのかが分からない事が多々あります。
オープンAPIなどでは、データは最低限の内容保証しかしませんよ、的なサービスも多いので、例外エラーチェックは必須です。
外部サービスと同期処理をする場合にデータが返ってこず、ずっと処理を待ち続けるなんて事も発生してしまいます。
おまけ(システムエラー)
さて、今回は例外エラーを中心にお伝えしようと思っているので、あまり多くは語りませんが、システム的なエラーというものもあります。
これはプログラミングとしては全くエラーではありません。業務的なエラー内容をまとめて一覧化しておくなどして、エラー内容にマッチしたメッセージを表示するなどが一般的です。
今回お話している構文エラーや、例外とは別ものという事を認識sいておいて下さい。
例外処理「try-except」の使い方
では実際に例外処理であるtry-exceptについて紹介をしていきます。
基本的な使い方
例外処理というのは、まず何かの処理があって初めて発生します。ですから、実際に実行したい処理(例外が発生する可能性あり)とセットで記述する形になります。
記述の仕方は以下の様になります。
■try-exceptの書き方(実行はできません)
1 2 3 4 |
try: 処理(例外が発生する可能性あり) except エラー名: 例外発生時の処理 |
■簡単な解説
「try:」に続けて記述するのが、例外が発生する可能性はあるけど実行したい処理です。
ここで、実行処理の結果、何のエラーも発生しない場合は「except~」の処理は実行されません。
しかし、「except エラー名」で指定したエラーが発生した場合は、「例外発生時の処理を実行」する事になります。
try-exceptのサンプル
少し強引なコードですが、冒頭の「構文エラー」の部分に発生させた「NameError」をtry-exceptのエラーコードに指定してみましょう。
■Pythonコード
1 2 3 4 5 |
try: nowDT = datetime.now() print(nowDT) except NameError: print("時刻を取得できません") |
■実行結果
1 |
時刻を取得できません |
■解説
try-exceptでエラー指定しているため、構文エラーとはならずに例外処理として結果を出力できています。実はプログラム的に見れば、構文エラーであっても例外処理の一部としてキャッチする事ができるのです。
try-except後の処理
さて、try-exceptに続いて記述できる構文があるので、そちらもご紹介します。
・except節:exceptは実は何個でも記述可能です。
・else節:例外が発生しなかった場合に実行されます。
・finally説:例外発生の有無にかかわらず実行されます。
使い方は実際にサンプルを見ると分かると思います。「try-except」の構文でもよく使われるTypeErrorとZeroDivisionErrorを使ってサンプルコードを書いてみました。
■Pythonコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def sample(value): print("処理開始") try: result = 100 / value except TypeError: print("例外処理:TypeError") except ZeroDivisionError: print("例外処理:ZeroDivisionError") else: print("処理結果は" + str(result) + "です。") finally: print("処理終了") sample("A") sample(0) sample(1) |
■実行結果
1 2 3 4 5 6 7 8 9 |
処理開始 例外処理:TypeError 処理終了 処理開始 例外処理:ZeroDivisionError 処理終了 処理開始 処理結果は100.0です。 処理終了 |
■解説
sample関数に対して、様々な引数を与えています。
・引数が”A”⇒ TypeErrorが発生する (except節で指定)
・引数が0 ⇒ ZeroDivisionErrorが発生する(except節で指定)
・引数が1⇒ 例外は発生しない(else節で指定)
TypeErrorとZeroDivisionErrorの場合の例外処理を記述しています。この時except節を並べて記述していますね。それぞれのエラーに対する結果が表示されています。
※一点注意が必要なのは、両方のエラーに合致する場合は、最初に記述したエラー(この場合はTypeError)の例外処理となります。)
else節では例外が発生していない場合の処理をしていますね。
そして最後に、finally節では例外発生の有無にかかわらず、必ず処理がされています。
※わざわざfinallyとして書く内容でもないですが。。。
まとめ
「try-except」は実際のシステム開発では必須の構文です。本格的なシステム開発をしたことがあればご存じだとは思いますが、コードの大半はエラーのチェックで埋め尽くされるからです。
冒頭でもお伝えした様に、最近は外部のサーバからデータを引っ張るといったシステム構成も増えています。その場合は、どんな値が返るか分からない。という前提で設計をしなければなりません。
基本的には今回お伝えした内容が分かれば使いこなせると思います!なので、ここでぜひ見に付けておいて下さいね。