. Python中的異常棧跟蹤
之前在做Java的時候,異常對象默認就包含stacktrace相關的信息,通過異常對象的相關方法printStackTrace()和getStackTrace()等方法就可以取到異常棧信息,能打印到log輔助調(diào)試或者做一些別的事情。但是到了Python,在2.x中,異常對象可以是任何對象,經(jīng)??吹胶芏啻a是直接raise一個字符串出來,因此就不能像Java那樣方便的獲取異常棧了,因為異常對象和異常棧是分開的。而多數(shù)Python語言的書籍上重點在于描述Python中如何構(gòu)造異常對象和raise try except finally這些的使用,對調(diào)試程序起關鍵作用的stacktrace往往基本上不怎么涉及。
python中用于處理異常棧的模塊是traceback模塊,它提供了print_exception、format_exception等輸出異常棧等常用的工具函數(shù)。
def func(a, b):
returna / b
if__name__ =='__main__':
importsys
importtraceback
try:
func(1,0)
exceptExceptionase:
print"print exc"
traceback.print_exc(file=sys.stdout)
輸出結(jié)果:
print exc
Traceback (most recentcalllast):
File"./teststacktrace.py", line7,in
func(1,0)
File"./teststacktrace.py", line2,infunc
return? a / b
其實traceback.print_exc()函數(shù)只是traceback.print_exception()函數(shù)的一個簡寫形式,而它們獲取異常相關的數(shù)據(jù)都是通過sys.exc_info()函數(shù)得到的。
def func(a, b):
returna / b
if__name__ =='__main__':
importsys
importtraceback
try:
func(1,0)
exceptExceptionase:
print"print_exception()"
exc_type, exc_value, exc_tb = sys.exc_info()
print'the exc type is:', exc_type
print'the exc value is:', exc_value
print'the exc tb is:', exc_tb
traceback.print_exception(exc_type, exc_value, exc_tb)
輸出結(jié)果:
print_exception()
the exc typeis:
the exc valueis:integerdivisionormodulobyzero
the exc tbis:
Traceback (most recentcalllast):
File"./teststacktrace.py", line7,in
func(1,0)
File"./teststacktrace.py", line2,infunc
return? a / b
sys.exc_info()返回的值是一個元組,其中第一個元素,exc_type是異常的對象類型,exc_value是異常的值,exc_tb是一個traceback對象,對象中包含出錯的行數(shù)、位置等數(shù)據(jù)。然后通過print_exception函數(shù)對這些異常數(shù)據(jù)進行整理輸出。
traceback模塊提供了extract_tb函數(shù)來更加詳細的解釋traceback對象所包含的數(shù)據(jù):
def func(a, b):
returna / b
if__name__ =='__main__':
importsys
importtraceback
try:
func(1,0)
except:
_, _, exc_tb = sys.exc_info()
forfilename, linenum, funcname, sourceintraceback.extract_tb(exc_tb):
print"%-23s:%s '%s' in %s()"% (filename, linenum, source, funcname)
輸出結(jié)果:
samchimac:tracebacktest samchi$ python ./teststacktrace.py ./teststacktrace.py? ? :7'func(1,0)'in()./teststacktrace.py? ? :2'returna / b'infunc()
如果平時開發(fā)喜歡基于log的方式來調(diào)試,那么可能經(jīng)常去做這樣的事情,在log里面發(fā)現(xiàn)異常之后,因為信息不足,那么會再去額外加一些debug log來把相關變量的值輸出。調(diào)試完畢之后再把這些debug log去掉。其實沒必要這么麻煩,Python庫中提供了cgitb模塊來幫助做這些事情,它能夠輸出異常上下文所有相關變量的信息,不必每次自己再去手動加debug log。
cgitb的使用簡單的不能想象:
def func(a, b):
returna / b
if__name__ =='__main__':
importcgitb
cgitb.enable(format='text')
importsys
importtraceback
func(1,0)