Python 內建 try...except...finally 機制靈活強大,支援多重捕獲、異常鏈、跨層傳播與 logging 整合。本文系統整理核心語法、最佳實踐與常見陷阱,適用 Python 2.x/3.x 雙版本。
try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')
輸出:
try...
except: integer division or modulo by zero
finally...
END
try:
r = 10 / int('a')
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
else:
print('no error!')
finally:
print('finally...')
except 依序匹配,子類別必須寫在父類別之前,否則永不被捕獲(如 ValueError 是 StandardError 子類)。else 區塊:無異常時執行,適合放置「正常流程收尾」邏輯。def foo(s): return 10 / int(s)
def bar(s): return foo(s) * 2
def main():
try:
bar('0')
except StandardError as e:
print('Error!')
# logging.exception(e) # 記錄完整堆疊
finally:
print('finally...')
只需在最外層(或適當層級)捕獲,中間函式無需重複 try/except,大幅減少樣板碼。
import logging
logging.basicConfig(level=logging.ERROR)
try:
bar('0')
except StandardError as e:
logging.exception(e) # 自動包含堆疊追蹤
print('END') # 程式繼續執行
輸出含完整 Traceback,且程式不會終止;生產環境建議搭配 RotatingFileHandler 落盤。
class FooError(StandardError): pass
def foo(s):
n = int(s)
if n == 0:
raise FooError('invalid value: %s' % s)
return 10 / n
ValueError, TypeError, RuntimeError 等)語意更清晰。try:
10 / 0
except ZeroDivisionError:
raise ValueError('input error!') # 合理轉換
# 裸 raise 保留原始異常並繼續傳播
except StandardError as e:
logging.error(e)
raise
原則:轉換需符合語意邏輯,切勿將 IOError 強行轉為 ValueError。
except: 捕獲所有(含 KeyboardInterrupt, SystemExit)。finally 或使用 with 語句(Context Manager)。善用 try/except/finally 與 logging,能讓程式在錯誤發生時優雅降級、保留現場、持續服務。