【FastAPI 學習筆記 EP.6】錯誤處理 (Error Handling)

更新 發佈閱讀 9 分鐘

這篇文章將教你如何在 FastAPI 中正確攔截並處理錯誤,確保 API 在遇到異常時回傳標準化的 HTTP 狀態碼 (Status Code) 與清晰的錯誤訊息,避免程式無預警崩潰,並讓前端開發者能根據狀態碼精準判斷錯誤類型。

什麼是錯誤處理?

錯誤處理是指當 API 接收到無法處理的請求或發生內部問題時,主動中斷執行流程並回傳特定格式回應的機制。這就像自動販賣機在存貨不足時會顯示「售完」燈號並退幣,而不是直接吞錢當機。這能讓前端開發者明確知道發生了什麼問題(如權限不足、資源不存在),並據此顯示對應的 UI 提示。

錯誤處理基礎概念

1. 使用 HTTPException

這是 FastAPI 中最基本的錯誤拋出方式,當你 raise 這個異常時,FastAPI 會自動終止請求並回傳指定的 HTTP 回應。

from fastapi import FastAPI, HTTPException, status

app = FastAPI()

items = {"a": "Food","b": "3C"}

@app.get("/items/{item_id}")
async def read_item(item_id: str):
    if item_id not in items:
        # 當找不到項目時,中斷執行並回傳 404
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Item not found")
    return {"item": items[item_id]}

這段程式碼會檢查 item_id 是否存在,若不存在則直接拋出 HTTP 404 錯誤,客戶端會收到 JSON 格式的錯誤訊息。

2. 使用 status 常數

為了避免在程式碼中使用 Magic Numbers (例如 404、500),FastAPI 提供了 status 模組。使用具名的常數能提升程式碼的可讀性與維護性。

from fastapi import FastAPI, HTTPException, status

app = FastAPI()

@app.get("/users/{identity}")
async def read_user(identity: str):
    if identity == "admin":
        raise HTTPException(
            # 使用 status.HTTP_403_FORBIDDEN 代替數字 403
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Admin access is restricted"
        )
    return {"identity": identity}

使用 status.HTTP_403_FORBIDDEN 能讓開發者能直觀知道這是權限相關的錯誤,不需要查閱 HTTP 狀態碼對照表。

實作範例

以下範例模擬一個簡單的商品庫存系統。我們會根據不同的業務邏輯錯誤(找不到商品、庫存不足),回傳不同的 HTTP 狀態碼與錯誤訊息。

from fastapi import FastAPI, HTTPException, status

app = FastAPI()

# 模擬資料庫
inventory = {
    "apple": {"name": "Apple", "quantity": 10},
    "banana": {"name": "Banana", "quantity": 0}
}

@app.get("/buy/{item_name}/{count}")
async def buy_item(item_name: str, count: int):
    # 步驟 1: 檢查商品是否存在
    if item_name not in inventory:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"商品'{item_name}'不存在."
        )

    item = inventory[item_name]

    # 步驟 2: 檢查購買數量是否合法
    if count <= 0:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="購買數量必須大於0."
        )

    # 步驟 3: 檢查庫存是否足夠
    if item["quantity"] < count:
        raise HTTPException(
            status_code=status.HTTP_409_CONFLICT,
            detail=f"庫存數量不足,僅剩 {item['quantity']} 件."
        )

    # 扣除庫存並回傳成功訊息
    item["quantity"] -= count
    return {"message": f"成功購買了 {count} {item['name']}(個)", "remaining": item["quantity"]}

在此範例中,首先驗證商品是否存在,若無則回傳 404 (Not Found)。接著驗證請求數量是否大於 0,若否則回傳 400 (Bad Request),表示請求參數有誤。最後檢查庫存,若不足則回傳 409 (Conflict),表示資源狀態與請求衝突。每個錯誤情境都精準對應了合適的 HTTP 狀態碼。

常見錯誤與解決方法

1. 錯誤地使用 return 而非 raise

剛開始常誤以為要 return 一個錯誤物件,導致 FastAPI 把它當作正常回應處理,回傳 HTTP 200 OK,這會誤導前端判斷。

# 錯誤寫法:使用 return,狀態碼會變成 200 OK
if item_id not in items:
    return {"error": "Item not found"}

# 正確寫法:使用 raise 中斷請求,狀態碼正確為 404
if item_id not in items:
    raise HTTPException(status_code=404, detail="Item not found")

2. 使用不明確的狀態碼

雖然 HTTP 協定允許自定義狀態碼,但在標準 API 開發中,應該要盡量使用標準 HTTP 狀態碼。

# 錯誤寫法:全部錯誤都回傳 500 或自定義怪異數字
raise HTTPException(status_code=500, detail="User input error")

# 正確寫法:根據錯誤類型選擇語意正確的代碼 (如 400 參數錯誤)
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid user input")

結語

有效的錯誤處理是建構良好 API 的關鍵,請記住這三個重點:善用 raise HTTPException 來中斷異常流程、使用 status 來保持程式碼可讀性、並根據業務情境選擇最精確的 HTTP 狀態碼,這能讓你的 API 對接更順利,除錯更輕鬆。

留言
avatar-img
梧笙 WuSheng 的沙龍
65會員
14內容數
⛰️ 梧笙,意即「吾生」,我是一個平凡的理工宅男。 生活離不開 Code 與 Game,這裡主要紀錄與分享: 📖 學習筆記|紀錄我學習過的電腦技能與知識。 💻 科技新知|整理實用工具與科技領域的資訊。 🎮 電玩娛樂|聊聊遊戲動漫與實況直播的話題。 目前更新頻率不固定,有興趣歡迎追蹤。
2025/12/09
這篇文章將教你如何使用 FastAPI 的 Query 與 Path 函式,對 API 的輸入參數進行嚴格的格式驗證,並且為 API 文件添加描述資訊。
Thumbnail
2025/12/09
這篇文章將教你如何使用 FastAPI 的 Query 與 Path 函式,對 API 的輸入參數進行嚴格的格式驗證,並且為 API 文件添加描述資訊。
Thumbnail
2025/12/07
這篇文章將教你如何在 FastAPI 中定義與接收請求主體 (Request Body),當客戶端需要傳送 JSON 格式的詳細資料給伺服器(例如註冊表單或新增商品)時,就必須使用請求主體 (Request Body)。
Thumbnail
2025/12/07
這篇文章將教你如何在 FastAPI 中定義與接收請求主體 (Request Body),當客戶端需要傳送 JSON 格式的詳細資料給伺服器(例如註冊表單或新增商品)時,就必須使用請求主體 (Request Body)。
Thumbnail
2025/12/05
這篇文章將教你如何在 FastAPI 中宣告與使用查詢參數 (Query Parameters),讓你能實現資料過濾、搜尋與分頁等功能。
Thumbnail
2025/12/05
這篇文章將教你如何在 FastAPI 中宣告與使用查詢參數 (Query Parameters),讓你能實現資料過濾、搜尋與分頁等功能。
Thumbnail
看更多
你可能也想看
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
vocus 慶祝推出 App,舉辦 2026 全站慶。推出精選內容與數位商品折扣,訂單免費與紅包抽獎、新註冊會員專屬活動、Boba Boost 贊助抽紅包,以及全站徵文,並邀請你一起來回顧過去的一年, vocus 與創作者共同留下了哪些精彩創作。
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但開發出來之後, 我們會希望開放給一般使用者使用, 而一般使用者較能夠操作的媒介
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但開發出來之後, 我們會希望開放給一般使用者使用, 而一般使用者較能夠操作的媒介
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但我們除了能開發出應用之外, 也要設計的更人性化一點, API最重要的就是路由了
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」稍微帶大家認識了FastAPI這個框架, 它讓我們快速的架設一個API服務, 並提供了許多標準化功能, 只要照著規範走就能快速的開發出來, 但我們除了能開發出應用之外, 也要設計的更人性化一點, API最重要的就是路由了
Thumbnail
API是我們與其他系統介接的標準化規格, 那一份好的規格勢必要能夠達到引導與驗證的作用, 避免對方介接錯誤, 引發後續的災難性損失, 因此這一章節就是要教我們如何定義每個API的欄位怎麼填? 資料型態是什麼? 以及如何生成API文件。 我們在「【🔒 Python API框架篇 - Fas
Thumbnail
API是我們與其他系統介接的標準化規格, 那一份好的規格勢必要能夠達到引導與驗證的作用, 避免對方介接錯誤, 引發後續的災難性損失, 因此這一章節就是要教我們如何定義每個API的欄位怎麼填? 資料型態是什麼? 以及如何生成API文件。 我們在「【🔒 Python API框架篇 - Fas
Thumbnail
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有說明如何使用uvicorn來啟動FastAPI服務, 假設今天我們的API是一個CPU密集型的運算服務時, 通常我們會希望開啟多個行程來幫忙處理, 那麼大致上的撰寫方式會像這樣: app = FastAPI( ti
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有說明如何使用uvicorn來啟動FastAPI服務, 假設今天我們的API是一個CPU密集型的運算服務時, 通常我們會希望開啟多個行程來幫忙處理, 那麼大致上的撰寫方式會像這樣: app = FastAPI( ti
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有分享 FastAPI 這套API框架, 那麼當我們想要在應用程式剛執行時就註冊一些事件或者共享GPU運算模型、變數…等,當整個應用程式關閉時也進行釋放作業, 這樣的一個週期循環就是所謂的生命週期, 而在FastAPI這
Thumbnail
我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有分享 FastAPI 這套API框架, 那麼當我們想要在應用程式剛執行時就註冊一些事件或者共享GPU運算模型、變數…等,當整個應用程式關閉時也進行釋放作業, 這樣的一個週期循環就是所謂的生命週期, 而在FastAPI這
Thumbnail
當我們在開發一個AI應用服務時, 常常會需要載入大模型, But… 我們總不可能每一次的請求就載入一次模型吧! 這樣太沒有效率了, 也非常的浪費資源, 因此我們通常會希望應用程式啟動時就能夠載入模型, 之後每一次的請求只要讓模型進行運算即可, 那麼在FastAPI的框架中究竟要如何使用呢? 首
Thumbnail
當我們在開發一個AI應用服務時, 常常會需要載入大模型, But… 我們總不可能每一次的請求就載入一次模型吧! 這樣太沒有效率了, 也非常的浪費資源, 因此我們通常會希望應用程式啟動時就能夠載入模型, 之後每一次的請求只要讓模型進行運算即可, 那麼在FastAPI的框架中究竟要如何使用呢? 首
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News