HOWTO · Python

如何在 Python 中列印例外

了解如何在 Python 中列印例外、選擇錯誤訊息或完整 traceback,並避免常見的例外處理錯誤。

本頁內容

只需要錯誤訊息時,請使用 print(exception)。需要包含錯誤檔案和行號的完整 traceback 時,請在作用中的 except 區塊中使用 traceback.print_exc()。應針對具體例外類型進行處理;需要保留的診斷資訊應使用 logging,而不是 print()

列印例外訊息

將例外擷取為變數並傳遞給 print()。這是顯示錯誤原因的最簡單方式:

try:
    result = 10 / 0
except ZeroDivisionError as exc:
    print("Could not calculate result:", exc)

輸出:

Could not calculate result: division by zero

例外物件會轉換為訊息文字。此範例只擷取 ZeroDivisionError,因此不容易隱藏無關的程式設計錯誤。如果多個錯誤需要相同處理,可以在元組中列出類型,例如 except (TypeError, ValueError) as exc:

列印完整 traceback

訊息不一定能說明錯誤的來源。匯入 Python 內建的 traceback 模組,並在處理程式仍然作用時呼叫 print_exc()

import traceback

try:
    values = [1, 2]
    value = values[3]
except IndexError:
    traceback.print_exc()

輸出包含例外類型、訊息、檔案和失敗的行。當例外來自多層巢狀函式呼叫時,traceback 比單獨的訊息更有用。

print_exc() 會讀取目前正在處理的例外。在 except 區塊結束後呼叫,或在沒有作用中例外時呼叫,並不能恢復先前的 traceback;它可能輸出 NoneType: None。請把呼叫保留在處理程式中,或儲存例外後使用 print_exception() 進行明確控制。

明確控制 traceback 格式

traceback.print_exception() 接受例外物件,並可寫入指定的串流。當需要格式化或重新導向例外時很有用:

import sys
import traceback

try:
    int("not a number")
except ValueError as exc:
    traceback.print_exception(exc, file=sys.stdout)

要建立文字而不是立即列印,請使用 traceback.format_exception(exc)

import traceback

try:
    raise RuntimeError("configuration is missing")
except RuntimeError as exc:
    formatted = "".join(traceback.format_exception(exc))
    print(formatted)

traceback 函式預設保留例外鏈。因此,raise ... from ... 鏈可以同時顯示原始例外和新例外。只有在輸出規格要求時才限制 traceback 或停用例外鏈;刪除上下文會使診斷更困難。

自訂例外和 logging

當呼叫方需要區分領域錯誤和內建錯誤時,請定義自訂例外。擷取該類型並以相同方式列印訊息:

class ConfigurationError(Exception):
    pass

try:
    raise ConfigurationError("API key is missing")
except ConfigurationError as exc:
    print("Configuration failed:", exc)

在應用程式或服務中,建議在處理程式內使用 logging.exception()。它會記錄訊息和作用中的 traceback,日誌處理器還能將其傳送到檔案或監控系統:

import logging

try:
    load_settings()
except Exception:
    logging.exception("Loading settings failed")

load_settings() 替換為可能失敗的操作。範例在 logging 邊界刻意擷取寬泛的 Exception;一般應用程式邏輯應擷取自己確實能處理的具體例外類型。

常見錯誤和 FAQ

  • 不帶類型的 except: 也會擷取 KeyboardInterruptSystemExit。除非有專門理由處理 BaseException 的子類別,否則應避免使用。
  • 當程式無法產生有效結果時,不要只列印一般訊息然後靜默繼續。請重新引發例外,或返回明確的失敗結果。
  • type(exc) 顯示具體類別,str(exc) 顯示可讀訊息,repr(exc) 可能提供更具診斷性的表示。
  • 如果輸出要寫入日誌,請在處理程式內使用 logging.exception()。只需要簡短互動式診斷時,print(exc) 就足夠了。
  • traceback.print_exc() 用於目前正在處理的例外;保留例外物件並需要控制格式或輸出時,traceback.print_exception(exc) 更清楚。

這些模式使用 Python 內建的例外機制,不需要第三方套件。應根據需要的是訊息、完整呼叫路徑、格式化文字還是持久應用程式日誌來選擇方法。