例外
錯誤不是當機,是一條可以走的路。 · ⏱ 約 25 分鐘
你會學到三件事
try / except 接住錯誤,讓程式繼續
- 錯誤有名字,而名字就是它的種類
- 🔴 不要接住你不打算處理的東西
開始之前
第 3 課那件事還記得嗎——
n = int(input())
使用者打 abc 的話,程式當場停掉,後面全部不跑。
而使用者打錯字本來就會發生。那不是 bug,是你的程式該想過的情況。
一、try / except
try:
n = int("abc")
print("轉成了", n)
except ValueError:
print("那不是數字")
print("程式繼續")
輸出:
那不是數字
程式繼續
流程:
try 裡面出事的那一刻 → 剩下的【立刻跳過】 → 跳到 except → 之後正常往下走
⚠️ 出事那一行後面的東西不會跑——上面的 print("轉成了", n) 一次都沒印。
二、錯誤有名字
| 名字 |
什麼時候 |
ValueError |
值不對——int("abc") |
TypeError |
型別不對——"a" + 1 |
KeyError |
dict 沒有那個鍵 |
IndexError |
清單位置超出範圍 |
ZeroDivisionError |
除以零 |
NameError |
名字沒定義過 |
執行看看錯誤訊息,第一個字就是它的名字——那就是你要寫在 except 後面的。
拿到那個錯誤本身:
except ValueError as e:
print("出事了:", e)
三、🔴 不要接住你不打算處理的東西
try:
...
except: # 🔴 光禿禿的 except
pass
這樣寫會接住所有東西——包括:
- 你自己的打字錯誤(
NameError)
- 使用者按 Ctrl+C 想停掉程式
一個接住所有錯誤的程式,
和一個沒有錯誤的程式,看起來一模一樣。
而那正是最難查的一種 bug:它什麼都沒說,而它做錯了。
規則:except 後面永遠寫出你要接的那一種。
四、完整的形狀
try:
n = int(input())
except ValueError:
print("不是數字")
else:
print("成功讀到", n) # 沒出事才跑
finally:
print("不管有沒有出事都跑")
|
什麼時候 |
try |
可能出事的那一段 |
except X |
出的是 X 的話 |
else |
沒有出事的話(少用) |
finally |
不管怎樣都跑——關檔案之類的收尾 |
五、什麼時候該用它
✅ 使用者輸入 本來就可能亂打
✅ 讀檔案 檔案可能不存在
✅ 網路 可能斷線
🔴 自己的邏輯錯誤 ← 那要【修】,不是接住
例外是給「本來就會發生的意外」用的,
不是給「我還沒想清楚」用的。
完成的樣子
try:
n = int("abc")
print("轉成了", n)
except ValueError:
print("那不是數字")
print("程式繼續")
換你了
寫一個迴圈:一直要求使用者輸入數字,打錯就重問,
打對才往下走。
提示:while True: + try + 成功就 break。
這一課你做了什麼
- 你用
try / except 把一個錯誤變成了一條分支
- 你知道錯誤有名字,而名字就在錯誤訊息的第一個字
- 你知道光禿禿的
except 為什麼危險
如果卡住了
| 你看到 |
多半是因為 |
| 還是當掉了 |
except 的種類不對。先用 except Exception as e: print(e) 看看是什麼 |
try 裡面有些行沒跑 |
出事那一行後面的都會跳過,那是正常的 |
| 程式安靜地做錯事 |
用了光禿禿的 except,把真的 bug 也吞了 |
SyntaxError |
try 不能單獨存在,一定要配 except 或 finally |
在編輯器打開這一課 →