1. 程式人生 > >python-reraise重新丟擲自定義異常——如何使traceback選擇性保留?

python-reraise重新丟擲自定義異常——如何使traceback選擇性保留?

1. 自定義異常

 在python中,自定義一個異常類的方法如下:

新建一個python檔案exception.py,以後可以將該工程內的所有自定義異常類都寫到該檔案下。程式碼如下:

"""
自定義異常類
"""


# 引數型別異常類
class ParameterTypeError(Exception):
    _error_code = -1
    _error_type = "TypeError"

    def __init__(self, error_msg=""):    #可以理解為java的建構函式
        super().__init__(self)  # 初始化父類
        self.error_msg = error_msg    #設定建構函式的工作

    def __str__(self):    #設定轉化為string的格式
        return '錯誤型別:' + ParameterTypeError._error_type + ';錯誤提示:' + self.error_msg


if __name__ == '__main__':
    try:
        raise ParameterValueError('引數異常')
    except ParameterValueError as e:
        print(e)

2. 如何重新丟擲自定義異常?

如下程式碼,inner()方法會raise一個ConnectionError,在outer()方法中捕獲該異常,然後丟擲自定義的異常

def outer():
    try:
        inner()
    except Connection as e:
        raise ParameterValueError

3.traceback異常棧

如2程式碼 ,在python2及java的邏輯中,traceback會丟失捕捉的connectionError的異常資訊,只保留未捕捉的異常:

但在python3中,會預設附加上捕捉的上個異常的traceback資訊,如圖: 

要想忽略掉被捕捉的異常,需要在丟擲最後一個異常使用:

raise ParameterValueError from None

4.Traceback常用方法

在except程式碼塊中,使用以下方法,可以捕捉traceback相應資訊:

1. 

print('發生錯誤的檔案:', e.__traceback__.tb_frame.f_globals['__file__'])

print('錯誤所在的行號:', e.__traceback__.tb_lineno)

print('錯誤資訊', e)

2.(需要import sys)

sys.exc_info() 會返回一個3值元表 (type, value, traceback) ,其中:

  • type 從獲取到的異常中得到型別名稱,它是BaseException 的子類;
  • value 是捕獲到的異常例項;
  • traceback 是一個 traceback 物件。

3.(需要import traceback)

traceback.extract_tb(tb [,limit ] )返回一個堆疊中異常資訊(FrameSummary物件)列表,每一個物件是一個四元組(檔名,行號,函式名稱*,文字), limit為條數

示例程式碼:

if __name__ == '__main__':
    try:
        main()
    except ConnectionError as e:
        t, v, tb = sys.exc_info()
        print(traceback.extract_tb(tb, 2))
    raise ParameterValueError from None

輸出:

 

[<FrameSummary file /Users/mengxiangfen/project/tutor-ybc-course-pypackage/ybc_history/ybc_history/ybc_history.py, line 97 in <module>>, 
<FrameSummary file /Users/mengxiangfen/project/tutor-ybc-course-pypackage/ybc_history/ybc_history/ybc_history.py, line 91 in main>]

通過FrameSummary.filename, FrameSummary.lineno, FrameSummary.name可以獲取到檔名/行號 /函式名

5. 如何在Python2中保留之前的異常棧資訊?

https://mozillazg.com/2016/08/python-the-right-way-to-catch-exception-then-reraise-another-exception.html#hidpython-2