jupyterでインタラクティブにPythonを使っているとあまり必要ないのですが、
本番コードを書くときなどは流石に例外処理を真面目に実装する必要があることがあります。
そこまで高頻度にあることではなく、すぐ忘れてしまうので、書き方をまとめておこうと思います。
参考になるドキュメントは次の2箇所です。
8. エラーと例外
組み込み例外
基本的に次のような書き方になります。
必須なのは、 try と except で、 exceptは複数書くこともできます。
except する例外には as e のように別名をつけることができ、
別名をつけておけば処理中で利用できます。
else と finally はオプションなので不要ならば省略可能です。
try:
# ここに例外が発生しうるコードを書く
except [キャッチしたい例外クラス]:
# 例外が発生した時に実行するコード
else:
# 例外が発生なかった時に実行するコード
finally:
# 必ず実行するコード
とりあえず定番の 0で割る演算で試してみましょう。
import numpy as np
def inv(data):
try:
inverse_data = 1/data
except ZeroDivisionError as e:
print(e)
except TypeError as e:
print(e)
else:
print("正常終了")
return inverse_data
print("このメッセージは表示されない")
finally:
print("finallyに書いた文は必ず実行されます")
print(inv(5))
"""
正常終了
finallyに書いた文は必ず実行されます
0.2
"""
print(inv(0))
"""
division by zero
finallyに書いた文は必ず実行されます
None
"""
print(inv("a"))
"""
unsupported operand type(s) for /: 'int' and 'str'
finallyに書いた文は必ず実行されます
None
"""
例外が発生した、0と”a” については想定通りに動きました。
実は例外が発生しなかったinv(5)が僕にとっては少し驚きでした。
else: のブロックの中で、 return して関数を抜けているので、
それより後ろの finally: のブロックは流石に実行されないと思っていたのですが、
print関数がバッチリ実行されています。
改めてよく読んでみれば、ドキュメント中にもしっかりそう書いてありました。
この辺りはきちんと理解して使う必要がありそうです。
– もし try 文が break 文、 continue 文または return 文のいずれかに達すると、その:keyword:break 文、 continue 文または return 文の実行の直前に finally 節が実行されます。
– もし finally 節が return 文を含む場合、 try 節の return 文より先に、そしてその代わりに、 finally 節の return 文が実行されます。
今回はブログ記事用に書いたコードだったので、
ZeroDivisionError と TypeError を 分けて書きましたが、
Exception のようなキャッチできる範囲の広い例外を指定しておけばまとめて受け取ってくれます。
(本当はあまり良くないと思うのですが、便利なので大抵そうしています。)
def inv2(data):
try:
inverse_data = 1/data
return inverse_data
except Exception as e:
print(e)
return None
print(inv2(5))
"""
0.2
"""
print(inv2(0))
"""
division by zero
None
"""
print(inv2("a"))
"""
unsupported operand type(s) for /: 'int' and 'str'
None
"""
また、例外処理の中で例外の種類を区別する必要が全くない場合、
except Exception as e:
の代わりに、
except:
とだけ書いておけば、より簡単に全ての例外をキャッチしてくれます。
catchはどこから出てきた?
exceptでは?
ご指摘ありがとうございます。
確かに誤ってますね。修正させていただきました。