それでは下記の記事の続きをやっていこう!
👇前回までは<Style Guide編>と言うことで、Pythonを書く上での書き方の決まりごとや標準のルールを学習してきました。
今回は、エラー(Error)と例外(Exception)について学んでいきます。
プログラミングを学ぶ、それはエラーと戦うことと等しいですよね。エラーが出るたびに嫌になる気持ちは痛いほど分かりますが、コードの悪い箇所、原因を唯一教えてくれるのもまたエラーだけですよね。このエラーとうまく付き合っていくためには今回習う内容は必ず必要な知識となります、一緒に一つずつ確認しながら進めていこう🤓
それでは早速やっていこう!
Contents
Errorについて
エラーの種類
✅ Syntax error(構文エラー) : Pythonの書き方が正しくないケース
1 2 3 4 5 6 7 8 9 |
x = 0 if x == 0 # ← : が抜けている print(x / 0) <実行> File "/Users/~/PycharmProjects/StyleGuide/check_tool.py", line 2 if x == 0 ^ SyntaxError: invalid syntax |
✅ Exception(例外) : 書き方ではなく、プログラムが動かないケース
1 2 3 4 5 6 7 8 9 |
x = 0 if x == 0: print(x / 0) <実行> Traceback (most recent call last): File "/Users/~/PycharmProjects/StyleGuide/check_tool.py", line 3, in <module> print(x / 0) ZeroDivisionError: division by zero |
エラーが出たときの対処法(Tracebackの見方)
✅ Tracebackをしっかり読む
・どこでエラーが発生しているのか
・なぜエラーが発生したのか
・エラーメッセージ 等を表示してくれる。Tracebackを読むことでDebugをすることが出来る
Exceptionについて
✅ 例外が起きると、プログラムがクラッシュする
✅ 例外が起きる可能性がある処理を行う場合は、例外処理(Excption handling)する必要がある
✅ pythonには様々な例外がクラスとして定義されている(python公式で確認はこちら)
ZeroDivisionError: 0で割った時に起きる例外
1 2 3 4 |
x = 1 print(x / 0) <実行> ZeroDivisionError: division by zero |
TypeError: 関数や演算子の引数のタイプに問題がある時に起きる例外
1 2 3 |
print(1 + "1") <実行> TypeError: unsupported operand type(s) for +: 'int' and 'str' |
ValueError: 関数や演算子の引数のタイプは正しいが、値に問題がある時に起こる例外
1 2 3 |
int("two") <実行> ValueError: invalid literal for int() with base 10: 'two' |
try exceptの使い方(例外が起こってもクラッシュさせない方法)
✅ try, exceptを使うことでコードの実行中に例外が発生してもクラッシュさせないようにすることが出来る
✅try, exceptionの中のコードは最小にし、該当する箇所のみ入れる
👇まず、例外が発生してしまうコードの例です
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# 割り勘する関数(input関数の0を入力すると、例外が発生する) def split_bill(price): num = input("何人で割り勘しますか?") each = price / int(num) print(f"一人{each}円です") if __name__ == "__main__": split_bill(1000) <実行> # 0を入力 何人で割り勘しますか? 0 Traceback (most recent call last): File "/Users/username/PycharmProjects/Error/try_except.py", line 8, in <module> split_bill(1000) File "/Users/username/PycharmProjects/Error/try_except.py", line 4, in split_bill each = price / int(num) ZeroDivisionError: division by zero |
👇try, exceptで書き換えると以下のようになり、例外が発生しなくなる
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# 割り勘する関数(0、数字などの正しい値が入ってこなかった場合に例外を出さない) def split_bill(price): num = input("何人で割り勘しますか?") try: each = price / int(num) # ZeroDivisionErrorを例外処理 except ZeroDivisionError as e: print(e) print("0で割ることはできません。正しい値を入力して下さい") each =price # ValueErrorを例外処理 except ValueError: print("数字を入力してください") each = price print(f"一人{each}円です") if __name__ == "__main__": split_bill(1000) <実行> # 0を入力 何人で割り勘しますか? 0 division by zero 正しい値を入力して下さい 一人1000円です # fourを入力 何人で割り勘しますか? four 数字を入力してください 一人1000円です |
try, else, finallyの使い方(例外が起きなかった場合、必ず実行したい処理を追記)
✅ finally:例外処理(except)で捕まらずエラーを出力する場合でも、finallyで記述したコードは実行される
✅ finallyに達する前にtryでbreak, conrtinue, returnで終了しても、必ずfinallyは実行される
◎elseについて
try:
<例外が起こりうるコード>
except <例外> as <変数>:
<例外が起きた時に実行するコード>
else:
<例外が起きなかった時に実行するコード>
◎finallyについて
try:
<例外が起こりうるコード>
except <例外> as <変数>:
<例外が起きた時に実行するコード>
finally:
<必ず実行するコード>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# 割り勘する関数(finallyは必ず実行されることを検証) def split_bill(price): num = input("何人で割り勘しますか?") # try中returnを書き関数を終了させてみる try: each = price / int(num) return "try" except ZeroDivisionError as e: print(e) print("0で割ることはできません。正しい値を入力して下さい") except ValueError: print("数字を入力してください") else: print(f"一人{each}円です") # finally内にもreturnを記述 finally: print("ご利用ありがとうございます") return "finally" if __name__ == "__main__": print(split_bill(1000)) <実行> 何人で割り勘しますか? 10 ご利用ありがとうございます finally |
raiseの使い方(特定の例外を発生させる)
✅ raise <例外クラス> or raise <例外のインスタンス>の形をとる(ex. raise VlueError)
✅ try exceptのコードを実装した際、正しくコードが動作するかの確認に使う
1 2 3 4 5 6 7 |
try: # わざと例外を発生させることで、except内のコードをテストすることが出来る # TO DO ⇦後で削除するという意味のコメントになる raise ValueError() except ValueError: print("Do something") raise # コード内でraiseとすることで、エラーを発生させることが出来る |
例外(Exception)を自作する
✅ Exceptionクラスを継承する(BaseExceptionというビルドインクラスがあるが、継承されることを意図して設計されていないため注意)
✅自作するクラスの名前は”○○Error”という名前にしておくと分かりやすい
✅自作の例外はなるべく別のファイルに分ける
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# 自作Exeptinoを作成する # クラスの引数にはビルトインクラスの"Exception"を渡す class MyError(Exception): # MyErrorが呼ばれたら文字列を返すようにする def __str__(self): return "my error occurred" if __name__ == "__main__": response = input("y/n ?") if response != "y" and response != "n": raise MyError <実行> y/n ? i Traceback (most recent call last): File "/Users/<username>/PycharmProjects/Error/venv/myerror.py", line 11, in <module> raise MyError __main__.MyError: my error occurred |
型のチェックをする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
class Car(): def __init__(self, name): self.name = name def drive(self): print(f"I drive {self.name}!!") class Toyota(Car): def choose(self): print(f"I choose {self.name}!!") def drive_me(car: Car) -> None: # if type(car) is Car: # Toyota is CarとなりFalseとなってしまう # car.drive() # if isinstance(car, Car): method = getattr(car, "drive", None) # ⬇︎型のチェックをしていく if callable(method): car.drive() else: raise TypeError(f"{type(car).__name__}は運転(drive)できません") if __name__ == "__main__": collora = Toyota("Collora") drive_me(collora) # I drive Collora!! drive_me("collora") # TypeError: strは運転(drive)できません |
tracebackモジュール
✅EASP(erasier to ask for forgiveness than permission)の考え方でコードを書いていく
⬆︎コードが有効であると仮定して書いていく。その仮定が誤っていたら例外を出すようにする
⬆︎これにより手早くコードを書くことが可能
⬆︎try exceptを多く書くことにはなるが、それ自体は悪いことではない
✅どこでエラーが出ているのかを教えてくれるのがtracebackモジュール
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# ビルトインモジュールのtracebackをインポート import traceback def split_bill(price): num = input("割り勘する人数を教えてください") try: each = price / int(num) except ZeroDivisionError: print("0以外の数字を入力してください") else: print(f"一人{each}円です") def check(bill): total_bill = sum(bill.values()) try: split_bill(total_bill) except ValueError: # tracebackモジュールにより、エラーをtracebackしてくれるようになる traceback.print_exc() print("エラーが発生。やり直してください") if __name__ == "__main__": bill = {'burger' : 500, 'pasta' : 1400, 'fries' : 300, 'egg' : 200} check(bill) print("プログラムは問題なく実行されました") |
以上で、エラー(error)と例外(exception)については終了です、いかがだったでしょうか?
次回はCSVファイルの操作など、ファイルの入出力について学んでいきます。
pythonでデータを扱えるようになると、出来ることも大幅に広がっていきますので、どんどん学んでいきましょう!
今回はこの辺で、バイバイ👋
try:
<例外が起こりうるコード>
except <例外> as <変数>:
<例外が起きた時に実行するコード>