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:也會擷取KeyboardInterrupt和SystemExit。除非有專門理由處理BaseException的子類別,否則應避免使用。 - 當程式無法產生有效結果時,不要只列印一般訊息然後靜默繼續。請重新引發例外,或返回明確的失敗結果。
type(exc)顯示具體類別,str(exc)顯示可讀訊息,repr(exc)可能提供更具診斷性的表示。- 如果輸出要寫入日誌,請在處理程式內使用
logging.exception()。只需要簡短互動式診斷時,print(exc)就足夠了。 traceback.print_exc()用於目前正在處理的例外;保留例外物件並需要控制格式或輸出時,traceback.print_exception(exc)更清楚。
這些模式使用 Python 內建的例外機制,不需要第三方套件。應根據需要的是訊息、完整呼叫路徑、格式化文字還是持久應用程式日誌來選擇方法。