1. 程式人生 > 程式設計 >Python基於traceback模組獲取異常資訊

Python基於traceback模組獲取異常資訊

除了使用 sys.exc_info() 方法獲取更多的異常資訊之外,還可以使用 traceback 模組,該模組可以用來檢視異常的傳播軌跡,追蹤異常觸發的源頭。

下面示例顯示瞭如何顯示異常傳播軌跡:

class SelfException(Exception):
  pass
def main():
  firstMethod()
def firstMethod():
  secondMethod()
def secondMethod():
  thirdMethod()
def thirdMethod():
  raise SelfException("自定義異常資訊")
main()

上面程式中 main() 函式呼叫 firstMethod(),firstMethod() 呼叫 secondMethod(),secondMethod() 呼叫 thirdMethod(),thirdMethod() 直接引發一個 SelfException 異常。執行上面程式,將會看到如下所示的結果:

Traceback (most recent call last):
 File "C:\Users\mengma\Desktop\1.py",line 11,in <module>
  main()
 File "C:\Users\mengma\Desktop\1.py",line 4,in main          <--mian函式
  firstMethod()
 File "C:\Users\mengma\Desktop\1.py",line 6,in firstMethod    <--第三個
  secondMethod()
 File "C:\Users\mengma\Desktop\1.py",line 8,in secondMethod  <--第二個
  thirdMethod()
 File "C:\Users\mengma\Desktop\1.py",line 10,in thirdMethod   <--異常源頭
  raise SelfException("自定義異常資訊")
SelfException: 自定義異常資訊

從輸出結果可以看出,異常從 thirdMethod() 函式開始觸發,傳到 secondMethod() 函式,再傳到 firstMethod() 函式,最後傳到 main() 函式,在 main() 函式止,這個過程就是整個異常的傳播軌跡。

在實際應用程式的開發中,大多數複雜操作都會被分解成一系列函式或方法呼叫。這是因為,為了具有更好的可重用性,會將每個可重用的程式碼單元定義成函式或方法,將複雜任務逐漸分解為更易管理的小型子任務。由於一個大的業務功能需要由多個函式或方法來共同實現,在最終程式設計模型中,很多物件將通過一系列函式或方法呼叫來實現通訊,執行任務。

所以,當應用程式執行時,經常會發生一系列函式或方法呼叫,從而形成“函式呼叫戰”。異常的傳播則相反,只要異常沒有被完全捕獲(包括異常沒有被捕獲,或者異常被處理後重新引發了新異常),異常就從發生異常的函式或方法逐漸向外傳播,首先傳給該函式或方法的呼叫者,該函式或方法的呼叫者再傳給其呼叫者,直至最後傳到 Python 直譯器,此時 Python 直譯器會中止該程式,並列印異常的傳播軌跡資訊。

很多初學者一看到輸出結果所示的異常提示資訊,就會驚慌失措,他們以為程式出現了很多嚴重的錯誤,其實只有一個錯誤,系統提示那麼多行資訊,只不過是顯示異常依次觸發的軌跡。

其實,上面程式的運算結果顯示的異常傳播軌跡資訊非常清晰,它記錄了應用程式中執行停止的各個點。最後一行資訊詳細顯示了異常的型別和異常的詳細訊息。從這一行向上,逐個記錄了異常發生源頭、異常依次傳播所經過的軌跡,並標明異常發生在哪個檔案、哪一行、哪個函式處。

使用 traceback 模組檢視異常傳播軌跡,首先需要將 traceback 模組引入,該模組提供瞭如下兩個常用方法:

  • traceback.print_exc():將異常傳播軌跡資訊輸出到控制檯或指定檔案中。
  • format_exc():將異常傳播軌跡資訊轉換成字串。

可能有讀者好奇,從上面方法看不出它們到底處理哪個異常的傳播軌跡資訊。實際上我們常用的 print_exc() 是 print_exc([limit[,file]]) 省略了 limit、file 兩個引數的形式。而 print_exc([limit[,file]]) 的完整形式是 print_exception(etype,value,tb[,limit[,file]]),在完整形式中,前面三個引數用於分別指定異常的如下資訊:

  • etype:指定異常型別;
  • value:指定異常值;
  • tb:指定異常的traceback 資訊;

當程式處於 except 塊中時,該 except 塊所捕獲的異常資訊可通過 sys 物件來獲取,其中 sys.exc_type、sys.exc_value、sys.exc_traceback 就代表當前 except 塊內的異常型別、異常值和異常傳播軌跡。

簡單來說, print_exc([limit[,file]]) 相當於如下形式:

print_exception(sys.exc_etype,sys.exc_value,sys.exc_tb[,file]])

也就是說,使用 print_exc([limit[,file]]) 會自動處理當前 except 塊所捕獲的異常。該方法還涉及兩個引數:

limit:用於限制顯示異常傳播的層數,比如函式 A 呼叫函式 B,函式 B 發生了異常,如果指定 limit=1,則只顯示函式 A 裡面發生的異常。如果不設定 limit 引數,則預設全部顯示。
file:指定將異常傳播軌跡資訊輸出到指定檔案中。如果不指定該引數,則預設輸出到控制檯。

藉助於 traceback 模組的幫助,我們可以使用 except 塊捕獲異常,並在其中列印異常傳播資訊,包括把它輸出到檔案中。例如如下程式:

# 匯入trackback模組
import traceback
class SelfException(Exception): pass
def main():
  firstMethod()
def firstMethod():
  secondMethod()
def secondMethod():
  thirdMethod()
def thirdMethod():
  raise SelfException("自定義異常資訊")
try:
  main()
except:
  # 捕捉異常,並將異常傳播資訊輸出控制檯
  traceback.print_exc()
  # 捕捉異常,並將異常傳播資訊輸出指定檔案中
  traceback.print_exc(file=open('log.txt','a'))

上面程式第一行先匯入了 traceback 模組,接下來程式使用 except 捕獲程式的異常,並使用 traceback 的 print_exc() 方法輸出異常傳播資訊,分別將它輸出到控制檯和指定檔案中。

執行上面程式,同樣可以看到在控制檯輸出異常傳播資訊,而且在程式目錄下生成了一個 log.txt 檔案,該檔案中同樣記錄了異常傳播資訊。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。