文章

第18天:例外處理進階

課程簡介

在程式開發中,錯誤和異常是不可避免的。透過例外處理,我們可以在程式出現問題時給出適當的回應,並保持程式的穩定運行。今天,我們將學習例外處理的進階技巧,探索如何自定義例外、使用 elsefinally 關鍵字,以及如何處理多重例外。這些技巧將幫助我們建立更強壯、更易於維護的程式。


學習內容

1. 多個 except 區塊

在程式中,我們可以使用多個 except 區塊來處理不同的例外類型。這樣可以針對不同的錯誤類型進行特定的處理。

範例:

1
2
3
4
5
6
7
try:
    num = int(input("Enter a number: "))
    result = 10 / num
except ValueError:
    print("請輸入一個數字!")
except ZeroDivisionError:
    print("不能除以零!")

在這個範例中,我們分別處理了 ValueError(當輸入不是數字時)和 ZeroDivisionError(當除以零時)的情況。

2. else 子句

else 子句可以與 try 區塊一起使用,當 try 區塊沒有拋出例外時,else 區塊中的程式碼將會被執行。

範例:

1
2
3
4
5
6
try:
    num = int(input("Enter a number: "))
except ValueError:
    print("請輸入一個數字!")
else:
    print(f"輸入的數字是 {num}")

如果使用者輸入了一個有效的數字,則 else 區塊中的程式碼將會執行。

3. finally 子句

無論是否發生例外,finally 區塊中的程式碼都會被執行,這在需要進行資源釋放(例如關閉檔案、釋放記憶體等)的情況下特別有用。

範例:

1
2
3
4
5
6
7
8
try:
    file = open("data.txt", "r")
    data = file.read()
except FileNotFoundError:
    print("找不到檔案!")
finally:
    file.close() # NameError: name 'file' is not defined
    print("檔案已關閉。")

在這裡,即使檔案找不到,finally 區塊中的 file.close() 仍然會執行。

4. 自定義例外

Python 允許開發者定義自己的例外類別,這有助於在特定情況下拋出更加有意義的錯誤。自定義例外需要繼承自內建的 Exception 類別。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class NegativeNumberError(Exception):
    def __init__(self, value):
        self.value = value
        super().__init__(f"不允許負數: {self.value}")

def check_positive(num):
    if num < 0:
        raise NegativeNumberError(num)

try:
    num = int(input("Enter a positive number: "))
    check_positive(num)
except NegativeNumberError as e:
    print(e)

在這個範例中,NegativeNumberError 是一個自定義的例外類別,當輸入負數時,會拋出這個例外並顯示相應的訊息。

5. 捕獲所有例外

有時,我們可能需要捕獲所有可能發生的例外。這可以通過捕獲 Exception 類別來實現,但這種方法應謹慎使用,因為它可能掩蓋程式中的真實錯誤。

範例:

1
2
3
4
try:
    result = 10 / int(input("Enter a number: "))
except Exception as e:
    print(f"發生錯誤: {e}")

這裡,無論是什麼類型的錯誤,都會被捕獲並輸出錯誤訊息。

6. 多重例外處理

當我們需要在同一個 except 區塊中捕獲多個例外時,可以將它們放在一個元組中來處理。

範例:

1
2
3
4
5
try:
    num = int(input("Enter a number: "))
    result = 10 / num
except (ValueError, ZeroDivisionError) as e:
    print(f"發生錯誤: {e}")

在這個範例中,ValueErrorZeroDivisionError 都會被捕獲並由相同的 except 區塊處理。


教學重點

  • 多個 except 區塊:學會根據不同的例外類型進行不同的處理。
  • else 子句:理解如何在例外沒有發生時,使用 else 來執行特定的程式碼。
  • finally 子句:掌握如何使用 finally 來確保資源釋放或執行必須的清理工作。
  • 自定義例外:學習如何定義和拋出自定義例外,來處理特定的錯誤情況。
  • 捕獲所有例外:理解如何捕獲所有例外,但應謹慎使用。
  • 多重例外處理:學會如何在一個 except 區塊中處理多種例外。

任務

  1. 創建一個函數 divide(a, b),要求輸入兩個數字,並處理 ZeroDivisionErrorValueError 兩種例外。
  2. 定義一個自定義例外類別 InvalidAgeError,當輸入的年齡小於 0 或大於 120 時,拋出這個例外並顯示適當的錯誤訊息。
  3. 使用 finally 子句來實現一個檔案讀取操作,即使檔案操作出錯,也能確保檔案被正確關閉。
  4. 寫一個程式,要求使用者輸入一個正整數,若輸入的數字不是正整數或發生其他錯誤,使用 Exception 捕獲並顯示相應的錯誤訊息。
本文章以 CC BY 4.0 授權