只获取最后一个回溯而不使用 None 的 raise?
Get only last traceback without using raise from None?
我在我的项目中有一个常见的情况,我使用自定义异常来包装内置的异常场景,例如:
# meaningless here but in other situations its useful...
try:
5/0
except ZeroDivisionError as e:
raise MyCustomException(msg=str(e))
连同通用异常处理程序,如下所示:
@app.errorhandler(Exception) # this decorator is flask related - ignore it
def handle_error(error):
if isinstance(error, MyCustomException):
# some code
# I only want MyCustomException traceback
else:
# some other code
exc_stack = traceback.format_exc(limit=5)
这里的已知问题是我得到了两个异常回溯,而在 if-case 中我只想要最后一个。
这个问题据我所知有两种解法
第一个解决方法(使用 from None
):
try:
5/0
except ZeroDivisionError as e:
raise MyCustomException(msg=str(e)) from None # python3
第二种解决方法(在引发第二个异常之前调用回溯)
try:
5/0
except ZeroDivisionError as e:
tracb = traceback.format_exc(limit=5)
raise MyCustomException(msg=str(e), tracb_msg=tracb)
无需在异常处理程序中调用traceback.format_exc()
,只需使用传递给实例的tracb_msg
。显然第一个解决方法更简单。
我的问题:
这两种方法在代码中重复出现(重复 code/trick)数十次,每次 我提出 MyCustomException
。有没有人想出一个技巧来在处理函数中处理这个一次?
使用 __suppress_context__
属性禁用上下文打印。
根据 docs,使用 raise MyCustomException(foo) from bar
将 __cause__
设置为 bar
,并将 __context__
设置为原始异常(隐式链接异常)。
An implicitly chained exception in __context__
is shown only if __cause__
is None and __suppress_context__
is false.
这是一个例子:
# Declare an exception that never shows context.
class MyCustomException(Exception):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__suppress_context__ = True
try:
1/0
except ZeroDivisionError as e:
raise MyCustomException(str(e))
这是我得到的输出:
Traceback (most recent call last):
File "/home/don/workspace/scratch/scratch.py", line 12, in <module>
raise MyCustomException(str(e))
MyCustomException: division by zero
这是我将 __suppress_context__
设置为 False
的输出:
Traceback (most recent call last):
File "/home/don/workspace/scratch/scratch.py", line 10, in <module>
1/0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/don/workspace/scratch/scratch.py", line 12, in <module>
raise MyCustomException(str(e))
MyCustomException: division by zero
我在我的项目中有一个常见的情况,我使用自定义异常来包装内置的异常场景,例如:
# meaningless here but in other situations its useful...
try:
5/0
except ZeroDivisionError as e:
raise MyCustomException(msg=str(e))
连同通用异常处理程序,如下所示:
@app.errorhandler(Exception) # this decorator is flask related - ignore it
def handle_error(error):
if isinstance(error, MyCustomException):
# some code
# I only want MyCustomException traceback
else:
# some other code
exc_stack = traceback.format_exc(limit=5)
这里的已知问题是我得到了两个异常回溯,而在 if-case 中我只想要最后一个。
这个问题据我所知有两种解法
第一个解决方法(使用 from None
):
try:
5/0
except ZeroDivisionError as e:
raise MyCustomException(msg=str(e)) from None # python3
第二种解决方法(在引发第二个异常之前调用回溯)
try:
5/0
except ZeroDivisionError as e:
tracb = traceback.format_exc(limit=5)
raise MyCustomException(msg=str(e), tracb_msg=tracb)
无需在异常处理程序中调用traceback.format_exc()
,只需使用传递给实例的tracb_msg
。显然第一个解决方法更简单。
我的问题:
这两种方法在代码中重复出现(重复 code/trick)数十次,每次 我提出 MyCustomException
。有没有人想出一个技巧来在处理函数中处理这个一次?
使用 __suppress_context__
属性禁用上下文打印。
根据 docs,使用 raise MyCustomException(foo) from bar
将 __cause__
设置为 bar
,并将 __context__
设置为原始异常(隐式链接异常)。
An implicitly chained exception in
__context__
is shown only if__cause__
is None and__suppress_context__
is false.
这是一个例子:
# Declare an exception that never shows context.
class MyCustomException(Exception):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__suppress_context__ = True
try:
1/0
except ZeroDivisionError as e:
raise MyCustomException(str(e))
这是我得到的输出:
Traceback (most recent call last):
File "/home/don/workspace/scratch/scratch.py", line 12, in <module>
raise MyCustomException(str(e))
MyCustomException: division by zero
这是我将 __suppress_context__
设置为 False
的输出:
Traceback (most recent call last):
File "/home/don/workspace/scratch/scratch.py", line 10, in <module>
1/0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/don/workspace/scratch/scratch.py", line 12, in <module>
raise MyCustomException(str(e))
MyCustomException: division by zero