例外処理とは?
今回はPythonで例外処理の方法を解説していきたいと思います。
まずは例外処理という言葉は馴染みがないので、言葉の解説から始めていきたいと思います。
プログラムを実行した時、起きるのは「正常終了」か「異常終了」の二つです。
正常終了は、最後までプログラムが意図した通りに処理が終了することです。
異常終了は、プログラムの途中でプログラムとして意図されていない処理が行われ、終了した状態を指します。
正常終了した場合は、意図した通りなので問題では無いのですが、異常終了の場合は意図していない処理が行われているため、プログラムとして問題なわけです。
ということで異常終了の原因を探っていきます。
異常終了の原因としては、プログラマーが前もって想定できる原因と、想定できない原因があるわけです。
そのうち前もって想定できる原因に対して、その処理法を書いておくのが「例外処理」ということです。
例:二つの変数で掛け算をしてみる
例えば、変数xとyを使って、二つの数字の掛け算を行い、表示するこのプログラム。
x = 2
y = 3
print(x * y)
実行結果
6
両方とも数字(int)なら問題なく、答えが計算されます。
しかし両方ともダブルクオーテーションでくくり、文字(str)としての数字に変えてみます。
x = "2"
y = "3"
print(x * y)
実行結果
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-XX-XXXXXXXXXXXX> in <module>
2 y = "3"
3
----> 4 print(x * y)
TypeError: can't multiply sequence by non-int of type 'str'
このようにエラーが表示されます。
このエラーを補足(キャッチといいます)して、処理をするのが例外処理ということです。
try – except文の基本的な使い方
Pythonで例外処理を行う場合、使われる構文が「try – except」になります。
一番基本的な書き方としては、こんな感じです。
try:
試したい処理
except:
エラーだった場合の処理
先ほどの二つの変数を掛け合わせるプログラムを使って、エラーが出る場合はErrorと表示させてみましょう。
try:
print(x * y)
except:
print("Error")
このプログラムでx = 3、y = 2と両方とも数字(int)の場合はこうなります。
x = 3
y = 2
try:
print(x * y)
except:
print("Error")
実行結果
6
普通に3×2が計算されて、6が表示されます。
次にx = “3”、y = “2”、つまり文字(str)としての数字にしてみましょう。
x = "3"
y = "2"
try:
print(x * y)
except:
print("Error")
実行結果
Error
この場合は “3” × “2”ではエラーが出て処理できないため、exceptに書いたの処理が行われ、Errorが表示されます。
エラーではなかった場合のみ続けて処理する:else
次にtryで書いたプログラムでエラーが出なかった場合のみ、さらに処理する方法を解説します。
その際に使うのが「else」です。
elseを使って、正常に処理できた場合、Goodと表示させてみます。
try:
print(x * y)
except:
print("Error")
else:
print("Good")
これでx = 3、y = 2、つまり両方とも数字(int)を入れてみます。
x = 3
y = 2
try:
print(x * y)
except:
print("Error")
else:
print("Good")
実行結果
6
Good
では数字(int)ではなく、両方とも文字(str)を入れた場合(x = “3”、y = “2”)はどうでしょうか。
x = "3"
y = "2"
try:
print(x * y)
except:
print("Error")
else:
print("Good")
実行結果
Error
この場合は、elseに書かれたプログラムは実行されないため、Goodは表示されません。
エラーに関係なく続けて処理する:finally
tryでの処理がエラーになっても、ならなくても続けて処理する場合、finallyを使います。
ということでエラーに関係なく、プログラムの最後に「Finish」と表示させてみます。
x = 3
y = 2
try:
print(x * y)
except:
print("Error")
else:
print("Good")
finally:
print("Finish")
両方とも数字の場合(x = 2、y = 3)はこうなります。
x = 3
y = 2
try:
print(x * y)
except:
print("Error")
else:
print("Good")
finally:
print("Finish")
実行結果
6
Good
Finish
tryでの処理により6が、elseでの処理によりGoodが、finallyの処理によりFinishが表示されます。
次に両方とも文字の場合(x = “3”、y = “2”)はこういう結果になります。
x = "3"
y = "2"
try:
print(x * y)
except:
print("Error")
else:
print("Good")
finally:
print("Finish")
実行結果
Error
Finish
この場合、tryでの処理に失敗しているため、exceptの処理が行われErrorが表示され、さらにfinallyの処理が行われるためFinishが表示されます。
ということで今回は例外処理 try – except文の基本を解説してみました。
この例外処理ができるようになると、条件分岐なんかにも使えて便利なので、是非とも習得していきたいものです。
全ての例外をキャッチ = except:
これまで解説で使ってきた「except:」という書き方は、どんなエラーだったとして区別なくキャッチします。
前回の解説ではx = “3”、y = “2”として両方とも文字(str)としての数字にすることでエラーを発生させました。
x = "3"
y = "2"
try:
print(x * y)
except:
print("Error")
実行結果
Error
例えばtryでの処理 print(x * y)のうち、yを定義していない変数zにしてみましょう。
x = "3"
y = "2"
try:
print(x * z)
except:
print("Error")
実行結果
Error
この場合でもtryで書かれた処理 print(x * z)はエラーとなるので、exceptの処理が行われ、Errorが表示されます。
つまり、「except:」として例外処理した場合、どんなエラーだったとしても、エラーが発生した場合、exceptに書かれた処理が行われます。
特定の例外をキャッチ = except XXX:
では特定の例外をキャッチして、処理する場合はどうするのでしょうか。
その場合は起こりうるエラーを知っておく必要があります。
今回、想定するエラーは下の二つです。
- 二つの変数が両方とも文字(str)である
- 少なくとも一つの変数が定義されていない
この場合、どのようなエラーが起こるか確認してみましょう。
二つの変数が両方とも文字(str)である場合
x = "2"
y = "3"
print(x * y)
実行結果
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-XX-XXXXXXXXXXXX> in <module>
2 y = "3"
3
----> 4 print(x * y)
TypeError: can't multiply sequence by non-int of type 'str'
少なくとも一つの変数が定義されていない
x = "2"
y = "3"
print(x * z)
実行結果
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-XX-XXXXXXXXXXXX> in <module>
2 y = "3"
3
----> 4 print(x * z)
NameError: name 'z' is not defined
ここで重要なのはエラー表示の最初の言葉になります。
- 二つの変数が両方とも文字(str)である = TypeError
- 少なくとも一つの変数が定義されていない = NameError
これがキャッチする例外の名前になります。
これをexceptの後ろに書くことで、特定の例外をキャッチすることができます。
今回はTypeErrorをキャッチし、Error:Typeと表示させてみましょう。
try:
print(x * y)
except TypeError:
print("Error:Type")
「二つの変数が両方とも文字(str)である」エラーの場合、実行結果はこうなります。
x = "3"
y = "2"
try:
print(x * y)
except TypeError:
print("Error:Type")
実行結果
Error:Type
ではキャッチすると定義されていないエラー(今回の場合、「少なくとも一つの変数が定義されていない」エラー)ではどうなるでしょうか。
x = "3"
y = "2"
try:
print(x * z)
except TypeError:
print("Error:Type")
実行結果
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-XX-XXXXXXXXXXXX> in <module>
3
4 try:
----> 5 print(x * z)
6 except TypeError:
7 print("Error:Type")
NameError: name 'z' is not defined
「少なくとも一つの変数が定義されていない」エラーは定義されていないため、キャッチできず通常のエラーとして処理され、プログラムが異常終了してしまいました。
複数の例外をキャッチ
特定の例外がキャッチできるようになると、複数の例外を別々にキャッチできるようになります。
ということでTypeErrorをキャッチし、Error:Typeと表示させたうえで、他のエラーは全てひとまとめにキャッチし、Errorと表示させてみましょう。
try:
print(x * z)
except TypeError:
print("Error:Type")
except:
print("Error")
このプログラムでTypeError(「二つの変数が両方とも文字(str)である」エラー)を発生させるとこうなります。
x = "3"
y = "2"
try:
print(x * y)
except TypeError:
print("Error:Type")
except:
print("Error")
実行結果
Error:Type
except TypeError: でエラーをキャッチして、Error:Typeが表示されています。
またその他のエラー(NameError: 「少なくとも一つの変数が定義されていない」エラー)の場合はこうなります。
x = "3"
y = "2"
try:
print(x * z)
except TypeError:
print("Error:Type")
except:
print("Error")
実行結果
Error
今度はexcept:でキャッチしているため、Errorが表示されています。
今回は一つを特定の例外をキャッチし、もう一つを例外全てをキャッチしていますが、複数の特定の例外をキャッチすることも可能です。
try:
print(x * z)
except TypeError:
print("Error:Type")
except NameError:
print("Error:Name")
こうすることにより、TypeErrorの場合はError:Typeと表示され、NameErrorの場合はError:Nameと表示されます。
例外をキャッチするがスルーする = pass
例外をキャッチするが、特に何もしない場合には「pass」を使います。
x = "3"
y = "2"
try:
print(x * y)
except TypeError:
pass
実行結果
この場合、except TypeError: でTypeError(二つの変数が両方とも文字(str)である)をキャッチしているのですが、処理に「pass」としているため、何もせず処理が終了しています。
そのため、実行結果には何も表示されません。
ということで2回に渡って、例外処理を解説してきました。
ちょっと難しい処理なので、なかなか使用場面をイメージすることができないかもしれません。
こうしている間にも前に導入した温度・湿度ロガーでデータが溜まってきていますし、そろそろ実践的なデータ処理を進めていきたいと思います。
その際になるべくこの例外処理を使って、色々試していくことにしましょう。
ということで今回はこんな感じで。
コメント