# Try-Except ## Sprout Py2021 @robert1003 ---- 想讓程式在壞掉後繼續跑? ---- ```python= # 我就 4 要除 0 print(1 / 0) ``` ``` ZeroDivisionError Traceback (most recent call last) <ipython-input-1-3ec96714f820> in <module> ----> 1 print(1 / 0) ZeroDivisionError: division by zero ``` ---- 怎麼對付他呢? --- ## Exception ---- * 一種特殊的 Class * 前面的 `ZeroDivisionError` 就是其中一種 * 所有的 Exception Class 們都是 Base Exception Class 的子孫 * [所有的 Base Exception Class](https://docs.python.org/3/library/exceptions.html#base-classes) --- ## try-except ---- 抓住所有的 Exception ```python= try: 你的 code except: 你的 code 爛掉就會跑來這裡 ``` ---- ValueError ```python= try: [].index(1) except: print('1 not in list') ``` ---- ZeroDivisionError ```python= try: print(1 / 0) except: print('cannot divide by 0') ``` ---- 自己 try try 看!想辦法寫個爛掉的 code ---- Question:可以處理排版錯誤嗎? ``` try: 1 / 0 1 / 0 except Exception as e: print(e, type(e)) ``` ``` IndentationError: unexpected indent ``` --- ## try-except-except 想抓住特定的錯誤? ---- 我只想把除零的 case 抓住,其他的讓他自然噴錯就好 ```python= try: 你的 code except 你想處理的Exception的名字: 你想處理的方法 except 你想處理的另一個Exception的名字: 你想處理的方法 ... ``` ---- ```python= try: print(1 / 0) # 會被抓住 except ZeroDivisionError: print('cannot divide by 0') ``` ---- ```python= try: print(1 / 0) # 會被抓住 [].index(0) # 不會被抓住 except ZeroDivisionError: print('cannot divide by 0') ``` ---- Question:會印出什麼? ```python= try: print(1 / 0) # ZeroDivisionError, 會被抓住 [].index(0) # ValueError, 會被抓住 [].find(0) # AttributeError, 不會被抓住 except ZeroDivisionError: print('cannot divide by 0') except ValueError: print('0 not in list') ``` ---- try-except-except 會執行到第一個錯誤為止 --- ## try-except-finally 不管有沒有發生錯誤都要執行的東西 ---- finally ```python= try: 你的 code except 處理其中一種 Exception: 處理的 code finally: 無論如何都會跑的 code ``` ---- ```python= try: print(1 / 0) except ZeroDivisionError: print('zero division error') finally: print('finally') ``` ---- 跟這個差在哪? ```python= try: print(1 / 0) except ZeroDivisionError: print('zero division error') print('finally') ``` ---- 你有 Exception 沒處理到的時候就會有差 ```python= try: [].index(0) # 不會被抓住 except ZeroDivisionError: print('zero division error') finally: print('finally') ``` --- ## raise 誰說自己不能生錯誤呢 ---- 自己噴錯 ```python= raise 你想噴的Exception instance ``` ---- 亂噴錯 ```python= x = int(input()) if x == 5: raise Exception("I don't like 5, go away") ``` ---- 亂噴錯2 ```python= x = int(input()) if x == 5: raise ZeroDivisionError("I don't like 5, go away") ``` ---- 小提醒:自己寫扣的時候亂噴錯沒關係,但跟別人合作的時候不能這樣,因為別人會看不懂為什麼爛掉 ---- 小練習:試試看自己 raise 一個 Exception 然後用上面教的 try-catch 把他抓住 --- ## custom exception 自己寫Exception Class ---- * 還記得前面說的嗎? * 「所有的 Exception Class 們都是 Base Exception Class 的子孫」 ---- ```python= class 你的Exception名字(Exception): # 繼承 Exception 這個 Base exception class pass ``` ---- 「我不喜歡5」Exception ```python= class IDontLikeFiveError(Exception): pass x = int(input()) if x == 5: raise IDontLikeFiveError("我不喜歡5") ``` ---- 小提醒: 1. Class 名稱通常都要首字母大寫 2. Exception Class 名稱通常都要 "Error" 結尾 ---- 小練習:自己建立一個 Exception Class 然後 raise 他 ---- 客製化自己的 Exception Class ```python= class IDontLikeError(Exception): def __init__(self, what, reason): self.what = what self.reason = reason def __str__(self): return "I don't like {} because {}".format(self.what, self.reason) x = int(input()) raise IDontLikeError(x, "我就4不喜歡") ``` ---- 小練習:客製化自己剛剛的 Exception Class,讓他的 error message 都加上一個 prefix "我就4不喜歡:" --- ## Q&A
{"metaMigratedAt":"2023-06-16T00:10:31.572Z","metaMigratedFrom":"YAML","title":"Try-Except","breaks":true,"slideOptions":"{\"transition\":\"slide\"}","contributors":"[{\"id\":\"3d3e812e-7132-40aa-b06f-8f5380bf64d1\",\"add\":11772,\"del\":8086}]"}
    495 views