錯誤處理
程式執行到一半,有時會遇到沒辦法處理的狀況:使用者把數字欄位填成文字、除數是 0、要開的檔案不存在……這些叫做錯誤(也叫異常,exception)。一發生,程式預設就會當場停下來報錯。這一章看怎麼接住這些錯誤,讓程式繼續好好走下去。
try / except:接住錯誤
Section titled “try / except:接住錯誤”把可能出錯的程式放進 try,萬一真的出錯,就跳到 except 那段。下面這段做除法,如果除數填 0,本來會壞掉,但 except 把它接住了。按「執行」,除數輸入 0 試試:
try: a = int(input("被除數:")) b = int(input("除數:")) print(a / b)except ZeroDivisionError: print("不能除以 0!")把除數改成別的數字再送出一次,程式就走正常的路,except 那段完全不會碰到。它只在真的出錯時才會跑。
針對不同的錯誤
Section titled “針對不同的錯誤”except 後面可以指定要接住哪一種錯誤。像 int("abc") 這種「轉不成數字」的情況會丟出 ValueError:
try: age = int(input("你的年齡:")) print("明年你", age + 1, "歲")except ValueError: print("請輸入數字,不要輸入文字")指定錯誤的種類是好習慣:你只接住預期中的錯誤,其他沒想到的問題還是會照常報出來,才不會把真正的 bug 藏起來。常見的錯誤還有 ZeroDivisionError(除以 0)、TypeError(型別用錯)、KeyError(字典沒有那個鍵)等等。
else 與 finally
Section titled “else 與 finally”完整的結構還有兩段:
else:try裡沒有出錯時才執行。finally:不管有沒有出錯,最後一定會執行,常用來做收尾(例如關檔)。
try: number = int(input("輸入一個數字:"))except ValueError: print("那不是數字")else: print("成功讀到", number)finally: print("結束(這行一定會執行)")輸入 7 會走 else,再走 finally;如果輸入文字,就改走 except,一樣會走到 finally。
raise:主動丟出錯誤
Section titled “raise:主動丟出錯誤”除了接住錯誤,你也可以在該擋的地方主動丟出錯誤,用的是 raise。這常拿來擋不合理的輸入:
def set_age(age): if age < 0: raise ValueError("年齡不能是負的")
print("年齡設為", age)
set_age(25)set_age(-3)set_age(25) 正常印出,但 set_age(-3) 因為年齡是負的就 raise 了一個 ValueError。這裡沒有 try 去接它,所以程式就停下來、報出這個錯誤。這正是 raise 的用意:把不該發生的事情大聲講出來,而不是默默算下去。