精確的異常處理與有保證的清理
僅在記錄預測和觀察到的證據之後,才允許使用輔助。
Prerequisites
完成上一項活動;如遇阻塞,使用所列恢復連結。
Learning Objective
預測檔案開啟成功與拋出 FileNotFoundError 時 try、except、else、finally 各執行哪些子句,然後驗證。把手動 close() 換成 with 區塊,並解釋為什麼禁止裸 except。
Instructions
try 放有風險的呼叫。except FileNotFoundError as e 只處理這一種預期失敗,e.filename 給出遺失路徑。else 只在無異常時執行;finally 總是執行。裸 except: 被禁止,因為它連 KeyboardInterrupt 和真正的程式錯誤也會吞掉,讓診斷變成瞎猜。對檔案物件來說,with 是預先定義的清理動作,有了它 finally 就不再必要。
Practice & Prediction Log
在一個空的暫存資料夾中操作。把這個腳本執行兩次:第一次 notes.txt 不存在,第二次先用 printf 'hi\n' > notes.txt 建立它再執行。
try:
f = open("notes.txt", encoding="utf-8")
except FileNotFoundError as e:
print("cannot open", e.filename)
else:
print("opened", f.name)
f.close()
finally:
print("cleanup")
每次執行前,寫下 try / except / else / finally 中哪些會執行以及確切輸出。然後 (1) 改寫成用 with 區塊關閉檔案,取代 else + f.close(),並展示區塊結束後 f.closed 為 True;(2) 舉出裸 except: 會隱藏的兩樣東西。
執行前逐行預測兩次執行。然後把 else/close() 部分改寫成 with 區塊,確認沒有 finally 子句檔案也會被關閉。
子句追蹤。notes.txt 不存在:open() 拋出 FileNotFoundError,所以 except 執行,else 被跳過,finally 執行:
cannot open notes.txt
cleanup
notes.txt 存在:try 成功,except 被跳過,else 執行(並關閉 f),finally 執行:
opened notes.txt
cleanup
基於 with 的改寫(儲存為 with_version.py,並在同樣兩種狀態下執行):
def show(path):
try:
with open(path, encoding="utf-8") as f:
print("opened", f.name)
except FileNotFoundError as e:
print("cannot open", e.filename)
return
print("closed after with:", f.closed)
show("notes.txt")
notes.txt 存在:
opened notes.txt
closed after with: True
notes.txt 不存在:
cannot open notes.txt
with 陳述式在區塊離開時(無論正常結束還是因異常)都會關閉檔案,所以對這個檔案來說,手動 close() 和 finally 子句都不再需要。except 留在 with 外面,因為拋出異常的正是 open() 本身。
裸 except: 會隱藏的兩樣東西:(1) KeyboardInterrupt(Ctrl+C)和 SystemExit,因為裸 except 會捕捉所有 BaseException;(2) 程式錯誤,例如拼字錯誤導致的 NameError。示範:
try:
prnt("hi")
except:
print("something went wrong")
something went wrong
拼錯的 print 拋出了 NameError,裸 except 卻把它回報成一個含糊的失敗。若用 except FileNotFoundError,同樣的拼字錯誤會以指向出錯行的 NameError traceback 顯露出來。
能準確說出成功與失敗各執行哪些子句,正確把 else/close() 改成 with 區塊,並舉出裸 except 會隱藏的兩樣東西。
Authoritative Source Resources & Provenance
The Python Tutorial: Errors and Exceptions
對應章節 / 時間戳: Sections 8.3–8.6 (handling exceptions, else, finally, cleanup actions)
驗證版本與日期: Python 3.12 documentation; verified 2026-10-30
Primary reference for try/except/else/finally semantics and the with statement as predefined cleanup.
Every clause behavior in the lesson is demonstrated by runnable local snippets.
對比候選資源與選型分析 (2)
Solid lecture treatment, but paced for a semester course and requires video viewing; the tutorial section matches the exercise scope directly.
Reference-style exception hierarchy listing rather than the tutorial narrative; retained as lookup material for the recovery drills.