Lesson 17 例外 ― Python言語の文法(応用編):機械学習&ディープラーニング入門(Python編)
本連載では、コードを書く流れに沿ってPython言語の基礎文法を説明してきた。今回は、応用的だが、利用頻度が高く重要な文法として、例外を紹介する。
ご注意:本記事は、@IT/Deep Insider編集部(デジタルアドバンテージ社)が「deepinsider.jp」というサイトから、内容を改変することなく、そのまま「@IT」へと転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。
Python言語の文法のうち、応用的だが押さえておいてほしいものをいくつか、具体的には、
- if 条件式(Lesson 14)
- and/or/not 論理演算子(Lesson 14)
- ラムダ式(Lesson 15)
- リスト内包表記(Lesson 16)
- 例外(Lesson 17)
の5項目を紹介してから終わりとしたい。これらは、Pythonのサンプルコードを読む際に出くわす可能性が特に高く、しかも知らないと非常に難解そうなコードに思えてしまうものたちである。そのうち今回は、「例外」について説明する。※脚注や図、コードリストの番号は前回からの続き番号としている。
なお、本稿で示すサンプルコードの実行環境については、Lesson 1を一読してほしい。
Lesson 1でも示したように、本連載のすべてのサンプルコードは、下記のリンク先で実行もしくは参照できる。
Python言語の文法(応用編)
例外
例外(exception)とは、いわゆる「エラー」(=プログラム上の異常事態)のことである。Pythonプログラムの実行途中で何らかのエラーが起こった際、意図せずに処理が中断してしまうことになる。エラーが起こったことをプログラムのユーザーに通知して何らかの対処を取った方がよい、という場面は多い。機械学習やディープラーニングでも、エラー発生時にメールなどで通知する処理を書きたいなどはあるだろう。
そういった例外処理を実現できるのが、try〜exceptという構文である。例えばデータ読み取りのために、あるファイルを開こうとして開けなかった場合、例外として捕捉(=キャッチ)してユーザーに通知したい、とする。
通常であれば、Pythonの組み込み関数のopen()関数でファイルを開き、その戻り値のファイルオブジェクトのreadlines()で全行を読み取り、close()関数でファイルを閉じる、というコードを記述する。リスト22-1がその例で、open()関数の引数にファイル名「'data.csv'」を指定している。ちなみに、close()関数を書く代わりにwithという構文を使って書くこともできるが、本稿では説明を割愛する。
f = open('data.csv')
lines = f.readlines()
f.close()
open()関数の引数に指定したdata.csvファイルがない状態でこのコードを実行すると、当然、例外が発生する。具体的には、図21のようにFileNotFoundErrorという例外(※Python 3系の場合。旧Python 2系ではIOError例外)が発生する。
この例外を捕捉してユーザーに通知するには、try文を使って、リスト22-2のように記述する。
try:
f = open('data.csv')
print('ファイルは正常に開けました。')
except FileNotFoundError as e:
#except IOError as e: # Python 2系の場合
print('ファイルがないようです。')
print(e) # [Errno 2] No such file or directory: 'data.csv'
raise
except:
print('何らかの例外が発生しました。')
raise
finally:
print('ここは常に最後に実行される。')
lines = f.readlines()
f.close()
try:の後にブロックが続き、後続のexcept <例外名>:/except:/finally:の後にもそれぞれブロックが続いている。構文としてはこれまでと同じワンパターンなので、もう構文のイメージ図は不要だろう。省略する。
try:の配下ブロックでは、例外が発生する可能性のあるコードを記述する。この例ではopen()関数を呼び出している。
except <例外名>:(<例外名>の後にas <別名>を足すことも可能)の配下ブロックに、例外の処理を記述する。<例外名>は、図21のFileNotFoundError(※Python 3系の場合。Python 2系ではIOError)を記述すればよい。これにより、指定した名前の例外がこのブロックで捕捉され、発生した例外に関する情報を含んでいるオブジェクトがas <別名>の<別名>に指定した名前の変数に代入される。ブロック内ではこの変数を利用して、(print(e)のように)例外についての情報を取り出せる。例外名については、実際に起きた例外で確かめるか、呼び出す関数のAPIリファレンスを見て確かめるしかない。
例外名が分からない、もしくはすべての例外を捕捉したい場合は、except:とその配下のブロックを記述すればよい。ちなみにリスト21-2の例では、except <例外名>:とexcept:の両方を記述しているが、もちろんexcept:だけを記述してもよい。
最後のfinally:とその配下のブロックは、省略することも可能で、try:の配下ブロックの完全実行後、もしくはexcept <例外名>:/except:の配下ブロックの実行が完了した後の、最後の最後に実行されることになる。例外であっても、例外でなくても、常に実行される点に注意が必要だ。
つづく
今回は、例外について説明した。次回はまとめとして、これまでの17回分のLessonのポイントを、箇条書きで短く再確認する。
Copyright© Digital Advantage Corp. All Rights Reserved.