Python 程式設計

第 14 章    例外處理

∗ 例外 (Exception):

▸ 程式語言對於無法利用一般流程控制來處理的情況所發出的訊息

▸ 在 Python 裡,所有程式錯誤 (Error) 都是透過例外來處理,但並非所有例外都是程式錯誤

(1) Python 的標準例外

∗ Python 有許多標準例外 (Standard exception),常見的如下:

語言例外說明
ImportError匯入錯誤
SyntaxError語法錯誤
IndentationError縮排錯誤
NameError識別字錯誤
TypeError資料型態錯誤
IndexError索引錯誤
KeyError鍵值錯誤

數學例外說明
OverflowError超過最大值錯誤
ZeroDivisionError除以 0 錯誤
FloatingPointError浮點運算錯誤

I/O例外說明
FileNotFoundError找不到檔案錯誤
IOError輸出入錯誤
PermissionError權限錯誤

▸ 其餘例外請參考這裡

(2) 例外擷取

∗ 擷取所有例外

▸ 不給 <exceptName>,則任何例外都會處理

try:
    ...
except:
    ...

∗ 擷取特定例外

▸ 給 <exceptName>,就只會處理該項例外

try:
    ...
except <exceptName>:
    ...

∗ 擷取多個例外

▸ 串連多個 except,如果沒有例外發生,就執行 else 部份

try:
    ...
except <exceptName1>:
    ...
except <exceptName2>:
    ...
except <exceptName3>:
    ...
else:
    ... 

∗ 例外處理後執行清理 (Clean-up) 程式

▸ 如果不論例外是否發生,都需要執行某些程式,可以寫在 finally 部份 (註:try: 部份可能有些程式不會執行)

try:
    ...
finally:    # 最後一定會執行
    ...

∗ 例外處理的要領

It's better to ask for forgiveness than permission: 錯了才請求原諒比每次請求允許要好

✶ 如果某些指令執行成功的機率較高,就直接執行,不需要判斷該指令是否會成功才執行,如此不僅程式效能較好,而且會顯得較為簡潔
✶ 反之,如果指令執行成功的機率較低,可以先判斷,然後決定是否執行該指令

▸ 範例:讀取檔案裡的數字字串,並轉為整數

ch13/input.txt (有些資料並非整數)
10 20 30 40
aa 20 30 40
10 bb 30 40
10 20 cc 40
10 20 30 dd
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
✶ 請求允許 (Ask for permission):四次判斷,程式冗長
ch13/permission.py
with open('input.txt', 'r') as infile:
    for line in infile:
        a, b, c, d = line.replace('\n', '').split()
        if not a.isdigit():    # 如果不是數字,就跳過這行
            continue
        a = int(a)
        if not b.isdigit():    # 如果不是數字,就跳過這行
            continue
        b = int(b)
        if not c.isdigit():    # 如果不是數字,就跳過這行
            continue
        c = int(c)
        if not d.isdigit():    # 如果不是數字,就跳過這行
            continue
        d = int(d)
        print(a, b, c, d)
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
✶ 請求原諒 (Ask for forgiveness):沒有判斷,程式簡潔
ch13/forgiveness.py
with open('input.txt', 'r') as infile:
    for line in infile:
        try:
            a, b, c, d = line.replace('\n', '').split()
            a, b, c, d = int(a), int(b), int(c), int(d)
            print(a, b, c, d)
        except:    # 只要有一個無法轉為整數,就跳過這行
            continue
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40
10 20 30 40

▸ 練習 1