Act 08. Pythonでエラーハンドリングを行う
はじめに
Act 01. AIで外国為替を自動売買するまでの道のりをベースに学習を進めて行く。
コードを書く上でエラーハンドリングはとても重要になってくる。
このシリーズでは外国為替のデータが必要なため、いつかはどこかのAPIを呼び出し為替データを取得することになる。
APIの呼び出しに失敗した場合にエラーハンドリングを行う必要があるため、今回の内容は身につける必要があることは現時点でも明確。とても重要。
何となくは理解しているが、復習もかねてしっかりと記事を書いていこうと思う。
エラーハンドリング
エラーハンドリングはtry-except
を使うことで実現可能。
例えば以下のコード。
x = 10 / 0
実行結果は以下の通りとなる。
0で割ることは出来ませんよ。と怒られる。
Traceback (most recent call last):
File "/home/onishi/python/Act08.py", line 1, in <module>
x = 10 / 0
~~~^~~
ZeroDivisionError: division by zero
try-except
を使うことで以下のようになる。
try:
x = 10 / 0
print(x)
except:
print("0で割れないよ!")
実行結果は以下の通り。
try
の中で何かしらのエラーが発生した場合にexcept
に遷移するため、print(x)
は実行されない。
0で割れないよ!
実際のエラーメッセージが欲しい場合は以下のように記述することで対応可能。
try:
x = 10 / 0
print(x)
except Exception as e:
print("0で割れないよ!")
print(e)
出力は以下の通り。
0で割れないよ!
division by zero
x = 10 / "0"
に変更した場合はどうなるか。
※数字の0で割るのではなく、文字列の0で割ろうとしている。
try:
x = 10 / "0"
print(x)
except Exception as e:
print("0で割れないよ!")
print(e)
出力は以下の通り。
タイプがおかしいと怒られる。
0で割れないよ!
unsupported operand type(s) for /: 'int' and 'str'
今回の場合は0で割れないよ!
というメッセージではなく、タイプがおかしいよ!にしたい。
どうすればよいか。
それは、エラーをタイプごとに分けることで実現が可能。
exceptの中身をprint(type(e))
と変更してみた。
try:
x = 10 / "0"
print(x)
except Exception as e:
print("0で割れないよ!")
print(type(e))
数値を文字列で割った場合のエラーはTypeError
であることが判明。
出力は以下の通り。
0で割れないよ!
<class 'TypeError'>
そのため、今回は以下のようにしてみる。
以下のように複数のexcept
を定義することで、エラーの型が一致している個所が実行される。
try:
x = 10 / "0"
except ZeroDivisionError as e:
print("0で割れないよ!")
print(e)
print(type(e))
except TypeError as e:
print("タイプがおかしいよ!")
print(e)
print(type(e))
出力は以下の通り。
タイプがおかしいよ!
unsupported operand type(s) for /: 'int' and 'str'
<class 'TypeError'>
次にfinally
について。
これは、エラーが発生した後に何かを実行したい場合に使う。
例えば、DBの接続を切る場合や、ファイルを閉じる場合など。
以下のように記述することで使用可能。
try:
x = 10 / "0"
except ZeroDivisionError as e:
print("0で割れないよ!")
print(e)
print(type(e))
except TypeError as e:
print("タイプがおかしいよ!")
print(e)
print(type(e))
finally:
print("最後に実行される。")
出力は以下の通り。
タイプがおかしいよ!
unsupported operand type(s) for /: 'int' and 'str'
<class 'TypeError'>
最後に実行される
finally
は正常に処理が終了した場合でも、異常終了した場合でも実行されるため、本当に最後に実行したいことだけを記述するようにする。
補足
一つ気になった。
except
内で再度エラーが発生した場合はどうなるのか。
try:
x = 10 / 0
except ZeroDivisionError as e:
print("0で割れないよ!")
print(e)
print(type(e))
x = 10 / 0
finally:
print("最後に実行される。")
出力結果は以下の通り。
finally
の中まで実行されて、その後にさらにエラーメッセージが出力される。
0で割れないよ!
division by zero
<class 'ZeroDivisionError'>
最後に実行される。
Traceback (most recent call last):
File "/home/onishi/python/Act08.py", line 2, in <module>
x = 10 / 0
~~~^~~
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/onishi/python/Act08.py", line 9, in <module>
x = 10 / 0
~~~^~~
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
(訳:上記の例外処理中に、別の例外が発生した)が出力された。
finally
も実行されるのは少し以外だったなー。
さいごに
エラーハンドリングは大事だからこそ業務でも使っていたし、特に新鮮味のないものだった。
まあ、新しいことも知れたし良かったとする。
それと、エラーハンドリングといったらログ出力も大事だから、予定とは変わっちゃうけど次回はlogging
モジュールについての記事にしようかな。
ではまた
Discussion