iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0

前言

寫程式的時候,你一定遇過這種場景:

輸入一個字串結果報錯、除以零整個程式崩潰、讀檔案時跳出紅字!!
整個畫面被滿滿的 Traceback 洗臉.....

這些情況,其實不是「壞掉」,而是程式在對你喊話:

「嘿!我遇到狀況啦,你想怎麼辦?」

這種狀況叫做 例外(Exception)。

例外處理就像程式的「安全氣囊」,
當錯誤發生時,能幫助程式不至於整個爆炸。

今天,我們要搞懂兩個層次:

  1. 例外處理基礎:try-except 機制與語法架構
  2. 例外進階應用:例外說明、堆疊傳遞、手動拋出例外等

學完這一章,你會發現——
錯誤不再是程式的敵人,而是可預測、可處理的事件。

ㄧ、什麼是例外?

例外(Exception)是程式執行時發生的錯誤。
不同於「語法錯誤(Syntax Error)」那種「一開始就不能跑」的錯,
例外是「能執行,但在執行過程中出現問題」!

常見例外

例外名稱 說明 範例
ZeroDivisionError 除以零 10 / 0
ValueError 型態錯誤 int('abc')
IndexError 索引超出範圍 [1,2,3][5]
KeyError 字典中找不到 key mydict['abc']
TypeError 型別不相容 "3" + 2
FileNotFoundError 找不到檔案 open('abc.txt')
NameError 使用未宣告變數 print(a)

例外處理的重點是:「接住錯誤、處理錯誤、不要讓程式崩潰」。

二、例外處理設計概念:EAFP vs LBYL

在 Python 世界裡,有兩種思維:

名稱 全名 思維方式 範例
EAFP Easier to Ask Forgiveness than Permission 直接嘗試、錯了再說抱歉(推薦風格) 用 try/except 先試後補
LBYL Look Before You Leap 先檢查能不能做,再執行 if os.path.exists() 再開檔案

Pythonic 寫法推薦 EAFP:

try:
    with open("data.txt") as f:
        content = f.read()
except FileNotFoundError:
    print("檔案不存在,建立新的 data.txt 檔案。")

EAFP 優點:程式更簡潔、可避免 race condition(檢查與操作之間狀態改變)

非推薦(LBYL)寫法:

if os.path.exists("data.txt"):
    f = open("data.txt")

三、例外處理語法

1.try / except

try:
    #受例外機制保護的程式區塊
    #區塊內若有例外狀況會停止繼續向下執行
    #先跳到except區塊
except :
    # 若發生特定例外,執行這裡

範例:

num1 = 10
num2 = 0
nums = [1, 3, 5, 7, 9,11]
try:
    print("進入到try區塊")
    print(num1 * num2)
    print(num1 / (num2))
    print(nums[100])
except:
    print("產生例外")
print('程式結束')

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/20164721LA0QnVbOYl.png

2.try / except 多例外類別

try:
    #受例外機制保護的程式區塊
except 例外類別一 :
    # try區塊產生例外類別一時,執行這裡
except 例外類別二 :
    # try區塊產生例外類別二時,執行這裡

範例:

num1 = 10
num2 = 0
nums = [1,3,5,7,9]
try:    
    print(num1/num2)
    print(num1*num3)
    print(nums[100])
except ZeroDivisionError:
    print('Error發生,除以0')
except NameError:
    print('Error發生,使用沒有宣告過的變數')

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/20164721WAFrLUf40L.png

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/201647212FIo3WGUdE.png

範例:

num1 = 10
num2 = 0
nums = [1,3,5,7,9]
try:    
    #print(num1/num2)
    #print(num1*num3)
    print(nums[100])
except ZeroDivisionError:
    print('Error發生,除以0')
except NameError:
    print('Error發生,使用沒有宣告過的變數')
except:
    print('Error發生')

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/201647215JJ8bNX34v.png

3.try / else

else 區塊只有在「沒有發生例外」時執行。

try:
    #受例外機制保護的程式區塊
    #區塊內若有例外狀況會停止繼續向下執行
else:
   #try區塊沒有產生例外時會執行else區塊

num1 = 10
num2 = 0
nums = [1,3,5,7,9]
try:
    print(num1/(num2+1))
    print(num1*num2)
    print(nums[4])
except:
    print('Error發生')
else:
    print('Error沒發生')

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/20164721WfguUztUZ4.png

4.try / finally

finally 無論是否發生例外都會執行,常用於關閉檔案、釋放資源等動作。

try:
    #受例外機制保護的程式區塊
    #區塊內若有例外狀況會停止繼續向下執行
finally:
   #不管try區塊如何,有沒有例外都會執行finally區塊

範例:

num1 = 10
num2 = 0
nums = [1,3,5,7,9]
try:
    print(num1/num2)
    print(num1*num3)
    print(nums[100])
except ZeroDivisionError:
    print('Error發生,除以0')
except NameError:
    print('Error發生,使用沒有宣告過的變數')
except IndexError:
    print('Error發生,索引值超出範圍')
except:
    print('Error發生')
finally:
    print('結束')

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/20164721b3VdnjbAf6.png

範例:

num1 = 10
num2 = 0
nums = [1,3,5,7,9]
try:
    print(num1/(num2+1))
    print(num1*num2)
    print(nums[4])
except:
    print('Error發生')
else:
    print('Error沒發生')
finally:
    print('結束')

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/20164721YtSDEkThmD.png

例外處理語法總結

try:
    # 嘗試執行的程式
except ExceptionType:
    # 若發生特定例外,執行這裡
else:
    # 若沒出錯,執行這裡
finally:
    # 無論如何都會執行(收尾動作)

四、例外進階處理

1.例外說明(Exception Description)

如果你想知道「錯誤的詳細內容」,可以用 as e 取得例外物件。

try:
    x = int(input("請輸入數字:"))
    y = 10 / x
except ValueError as e:
    print("錯誤型態:", type(e))
    print("錯誤內容:", str(e))

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/20164721f8uMbNu5IR.png

2.堆疊呼叫與例外傳遞

例外會「一路往上傳遞」,直到被捕捉或程式崩潰。

範例:

def a():
    b()

def b():
    c()

def c():
    raise ValueError("C出錯啦!")

try:
    a()
except Exception as e:
    print("捕捉到例外:", e)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/201647219XREJzfQ98.png

說明:

c()發生錯誤 → 傳到b()→ 傳到a()→ 最後被try捕捉。

這個過程叫例外傳遞(Exception Propagation)

3.手動拋出例外(raise)

除了捕捉錯誤,我們也能「自己丟出錯誤」。

def getResult(s):
    if 60<=score<=100:
        return '及格'
    elif(0<=score<60):
        return '不及格'
    else:        
        raise OverflowError

score=int(input('輸入成績:'))
try:
    res = getResult(score) 
except OverflowError:
    print("成績數值錯誤")
else:
    print("考試結果:", res)

輸出:
https://ithelp.ithome.com.tw/upload/images/20251009/20164721ZLtZiNQtNO.png

結語

今天辛苦啦!

寫程式其實不是要避免錯誤,而是要知道如何面對錯誤~
例外處理就是那把讓程式變「成熟」的工具!

今天我們學會了:

try / except / else / finally 的完整架構、
as e 捕捉錯誤說明、raise 主動丟出例外

當你開始用「例外」來思考,而不是害怕紅字報錯,
你就不只是寫程式的人,而是能設計穩定系統的人!!

再堅持一下!我們要衝過終點線囉!!
那麼我們就明天見~


上一篇
【Day24】模組與套件:能拆能組又能重複使用!
系列文
Python 小白的逆襲:30 天從零到能教人的精華筆記,寫給迷惘的你與當年的我自己!25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言