異常捕捉
通常我們在項目中,針對異常的捕捉會使用 try + except,基本形式如下:
try: # 主代碼 except IndexError as e: # 索引異常時執行這里 logger.debug(e) except KeyError as e: # 關鍵字異常時執行這里 logger.debug(e) except ValueError as e: # 值異常時執行這里 logger.debug(e) except Exception as e: # 萬能異常,若出現了與上述指定的異常不同的異常,就走這里 logger.debug(e)
上述方式有一個弊端,假設我們的主代碼中有一個報錯,那么日志輸出時只會有一行異常對象的值,我們無法追蹤定位到底是第幾行報錯,只能憑程序員的經驗或直覺去判斷。這時我們可以試試使用 traceback 模塊。
traceback
traceback 模塊提供三個方法
traceback.print_exc() # 在屏幕中輸出異常棧 traceback.format_exc() # 把異常棧以字符串的形式返回,print(traceback.format_exc()) 的效果相當於 traceback.print_exc() traceback.print_exception() # 其實traceback.print_exc()函數只是traceback.print_exception()函數的一個簡寫形式,而它們獲取異常相關的數據都是通過sys.exc_info()函數得到的
示例
def func(a, b): return a / b if __name__ == '__main__': import sys import traceback try: func(1, 0) except Exception as e: print("eeeeeeeeeeeeeeeeee") exc_type, exc_value, exc_tb = sys.exc_info() print(exc_type) print(exc_value) print(exc_tb) traceback.print_exception(exc_type, exc_value, exc_tb) # 效果等同於traceback.print_exc() ''' sys.exc_info()返回的值是一個元組, exc_type是異常的對象類型, exc_value是異常的值, exc_tb是一個traceback對象,對象中包含出錯的行數、位置等數據。 然后通過print_exception函數對這些異常數據進行整理輸出。 '''
其中,元祖的第三個元素 exc_tb 還可以細分
# traceback模塊提供了 extract_tb 函數來更加詳細的解釋 traceback 對象所包含的數據 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)) ''' 輸出結果: samchimac:tracebacktest samchi$ python ./teststacktrace.py ./teststacktrace.py :7 'func(1, 0)' in <module>() ./teststacktrace.py :2 'return a / b' in func() '''
寫入日志
traceback 的 三個方法中,print_exc() 和 print_exception() 都沒有返回值,只輸出到控制台(屏幕),如果要寫入日志,使用 format_exc(),日志的異常輸出會定位到具體行
import traceback try: # 主代碼 except IndexError as e: # 索引異常時執行這里 logger.debug(traceback.format_exc()) except KeyError as e: # 關鍵字異常時執行這里 logger.debug(traceback.format_exc()) except ValueError as e: # 值異常時執行這里 logger.debug(traceback.format_exc()) except Exception as e: # 萬能異常,若出現了與上述指定的異常不同的異常,就走這里 logger.debug(traceback.format_exc())
參考:https://www.jianshu.com/p/01ed4b8d7d9a