日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

搞清楚 Python traceback的具體使用方法

系統(tǒng) 1718 0

1. Python中的異常棧跟蹤

之前在做Java的時候,異常對象默認(rèn)就包含stacktrace相關(guān)的信息,通過異常對象的相關(guān)方法printStackTrace()和getStackTrace()等方法就可以取到異常棧信息,能打印到log輔助調(diào)試或者做一些別的事情。但是到了Python,在2.x中,異常對象可以是任何對象,經(jīng)常看到很多代碼是直接raise一個字符串出來,因此就不能像Java那樣方便的獲取異常棧了,因?yàn)楫惓ο蠛彤惓J欠珠_的。而多數(shù)Python語言的書籍上重點(diǎn)在于描述Python中如何構(gòu)造異常對象和raise try except finally這些的使用,對調(diào)試程序起關(guān)鍵作用的stacktrace往往基本上不怎么涉及。

python中用于處理異常棧的模塊是traceback模塊,它提供了print_exception、format_exception等輸出異常棧等常用的工具函數(shù)。

            
def func(a, b):
 return a / b
if __name__ == '__main__':
 import sys
 import traceback
 try:
 func(1, 0)
 except Exception as e:
 print "print exc"
 traceback.print_exc(file=sys.stdout)

          

輸出結(jié)果:

print exc
Traceback (most recent call last):
? File "./teststacktrace.py", line 7, in
??? func(1, 0)
? File "./teststacktrace.py", line 2, in func
??? return a / b

其實(shí)traceback.print_exc()函數(shù)只是traceback.print_exception()函數(shù)的一個簡寫形式,而它們獲取異常相關(guān)的數(shù)據(jù)都是通過sys.exc_info()函數(shù)得到的。

            
def func(a, b):
 return a / b
if __name__ == '__main__':
 import sys
 import traceback
 try:
 func(1, 0)
 except Exception as e:
 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 type is:
the exc value is: integer division or modulo by zero
the exc tb is:
Traceback (most recent call last):
? File "./teststacktrace.py", line 7, in
??? func(1, 0)
? File "./teststacktrace.py", line 2, in func
??? return a / b
ZeroDivisionError: integer division or modulo by zero

sys.exc_info()返回的值是一個元組,其中第一個元素,exc_type是異常的對象類型,exc_value是異常的值,exc_tb是一個traceback對象,對象中包含出錯的行數(shù)、位置等數(shù)據(jù)。然后通過print_exception函數(shù)對這些異常數(shù)據(jù)進(jìn)行整理輸出。
traceback模塊提供了extract_tb函數(shù)來更加詳細(xì)的解釋traceback對象所包含的數(shù)據(jù):

            
def func(a, b):
 return a / b
if __name__ == '__main__':
 import sys
 import traceback
 try:
 func(1, 0)
 except:
 _, _, exc_tb = sys.exc_info()
 for filename, linenum, funcname, source in traceback.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 'return a / b' in func()

2. 使用cgitb來簡化異常調(diào)試

如果平時開發(fā)喜歡基于log的方式來調(diào)試,那么可能經(jīng)常去做這樣的事情,在log里面發(fā)現(xiàn)異常之后,因?yàn)樾畔⒉蛔悖敲磿偃ヮ~外加一些debug log來把相關(guān)變量的值輸出。調(diào)試完畢之后再把這些debug log去掉。其實(shí)沒必要這么麻煩,Python庫中提供了cgitb模塊來幫助做這些事情,它能夠輸出異常上下文所有相關(guān)變量的信息,不必每次自己再去手動加debug log。

cgitb的使用簡單的不能想象:

            
def func(a, b):
    return a / b
if __name__ == '__main__':
    import cgitb
    cgitb.enable(format='text')
    import sys
    import traceback
    func(1, 0)

          

運(yùn)行之后就會得到詳細(xì)的數(shù)據(jù):

A problem occurred in a Python script.? Here is the sequence of
function calls leading up to the error, in the order they occurred.

?/Users/samchi/Documents/workspace/tracebacktest/teststacktrace.py in ()
??? 4 ?import cgitb
??? 5 ?cgitb.enable(format='text')
??? 6 ?import sys
??? 7 ?import traceback
??? 8 ?func(1, 0)
func =

?/Users/samchi/Documents/workspace/tracebacktest/teststacktrace.py in func(a=1, b=0)
??? 2 ?return a / b
??? 3 if __name__ == '__main__':
??? 4 ?import cgitb
??? 5 ?cgitb.enable(format='text')
??? 6 ?import sys
a = 1
b = 0

完全不必再去log.debug("a=%d" % a)了,個人感覺cgitb在線上環(huán)境不適合使用,適合在開發(fā)的過程中進(jìn)行調(diào)試,非常的方便。
也許你會問,cgitb為什么會這么?牛磕芑袢≌餉聰晗傅某齟硇畔??其實(shí)它的工作原理同它的使用方式一樣的簡單,它只是覆蓋了默認(rèn)的sys.excepthook函數(shù),sys.excepthook是一個默認(rèn)的全局異常攔截器,可以嘗試去自行對它修改:

            
def func(a, b):
    return a / b
def my_exception_handler(exc_type, exc_value, exc_tb):
    print "i caught the exception:", exc_type
    while exc_tb:
        print "the line no:", exc_tb.tb_lineno
        print "the frame locals:", exc_tb.tb_frame.f_locals
        exc_tb = exc_tb.tb_next
 
if __name__ == '__main__':
    import sys
    sys.excepthook = my_exception_handler
    import traceback
    func(1, 0)

          

輸出結(jié)果:

i caught the exception:
the line no: 14
the frame locals: {'my_exception_handler': , '__builtins__': , '__file__': './teststacktrace.py', 'traceback': , '__package__': None, 'sys': , 'func': , '__name__': '__main__', '__doc__': None}
the line no: 2
the frame locals: {'a': 1, 'b': 0}

看到?jīng)]有?沒有什么神奇的東西,只是從stack frame對象中獲取的相關(guān)變量的值。frame對象中還有很多神奇的屬性,就不一一探索了。

3. 使用logging模塊來記錄異常

在使用Java的時候,用log4j記錄異常很簡單,只要把Exception對象傳遞給log.error方法就可以了,但是在Python中就不行了,如果直接傳遞異常對象給log.error,那么只會在log里面出現(xiàn)一行異常對象的值。

在Python中正確的記錄Log方式應(yīng)該是這樣的:

            
logging.exception(ex)
logging.error(ex, exc_info=1) # 指名輸出棧蹤跡, logging.exception的內(nèi)部也是包了一層此做法
logging.critical(ex, exc_info=1) # 更加嚴(yán)重的錯誤級別

          

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 澄迈县| 蕲春县| 凌源市| 九寨沟县| 临汾市| 巢湖市| 桦川县| 镇远县| 怀集县| 临武县| 汝阳县| 英山县| 洛川县| 常德市| 霞浦县| 马尔康县| 泰兴市| 凌云县| 泰顺县| 新邵县| 盐池县| 固安县| 农安县| 汉川市| 南澳县| 镇雄县| 阿图什市| 商洛市| 祥云县| 金塔县| 定日县| 阳西县| 新安县| 霍州市| 博湖县| 平舆县| 常熟市| 广河县| 洞口县| 晋州市| 贵港市|