gpt4 book ai didi

python - 可以从 Python 异常回溯中删除装饰器吗?

转载 作者:太空宇宙 更新时间:2023-11-04 03:47:51 24 4
gpt4 key购买 nike

我有一些装饰器可以包装很多功能。当其中一个函数抛出错误时,我的回溯被许多装饰线污染了。有没有办法修改 python 装饰器,使其不会在异常回溯中打印自己?

下面是一些示例代码:

import functools


def dec(func):
@functools.wraps(func)
def wrap(*args, **kwargs):
return func(*args, **kwargs)
return wrap


@dec
def spam():
print('I sure hope nobody throws an Exception')
eggs()


@dec
def eggs():
raise Exception('Spanish Inquisition')


if __name__ == '__main__':
spam()

当我运行它时,我得到:

Traceback (most recent call last):
File "tmp.py", line 23, in <module>
spam()
File "tmp.py", line 7, in wrap
return func(*args, **kwargs)
File "tmp.py", line 14, in spam
eggs()
File "tmp.py", line 7, in wrap
return func(*args, **kwargs)
File "tmp.py", line 19, in eggs
raise Exception('Spanish Inquisition')
Exception: Spanish Inquisition

但我真正想要的是:

Traceback (most recent call last):
File "tmp.py", line 23, in <module>
spam()
File "tmp.py", line 14, in spam
eggs()
File "tmp.py", line 19, in eggs
raise Exception('Spanish Inquisition')
Exception: Spanish Inquisition

我该怎么做呢?

最佳答案

因此,我制作了一个装饰器 ignores_exc_tb,它似乎可以满足我的需求。我将在这里发布代码以及我正在使用它的真实代码:

import sys
from functools import wraps
from .util_iter import isiterable
from .util_print import Indenter


IGNORE_EXC_TB = not '--noignore-exctb' in sys.argv


def ignores_exc_tb(func):
""" decorator that removes other decorators from traceback """
if IGNORE_EXC_TB:
@wraps(func)
def wrapper_ignore_exctb(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception:
# Code to remove this decorator from traceback
exc_type, exc_value, exc_traceback = sys.exc_info()
# Remove two levels to remove this one as well
raise exc_type, exc_value, exc_traceback.tb_next.tb_next
return wrapper_ignore_exctb
else:
return func


def indent_decor(lbl):
def indent_decor_outer_wrapper(func):
@ignores_exc_tb
@wraps(func)
def indent_decor_inner_wrapper(*args, **kwargs):
with Indenter(lbl):
return func(*args, **kwargs)
return indent_decor_inner_wrapper
return indent_decor_outer_wrapper


def indent_func(func):
@wraps(func)
@indent_decor('[' + func.func_name + ']')
@ignores_exc_tb
def wrapper_indent_func(*args, **kwargs):
return func(*args, **kwargs)
return wrapper_indent_func


def accepts_scalar_input(func):
'''
accepts_scalar_input is a decorator which expects to be used on class methods.
It lets the user pass either a vector or a scalar to a function, as long as
the function treats everything like a vector. Input and output is sanatized
to the user expected format on return.
'''
@ignores_exc_tb
@wraps(func)
def wrapper_scalar_input(self, input_, *args, **kwargs):
is_scalar = not isiterable(input_)
if is_scalar:
iter_input = (input_,)
else:
iter_input = input_
result = func(self, iter_input, *args, **kwargs)
if is_scalar:
result = result[0]
return result
return wrapper_scalar_input


def accepts_scalar_input_vector_output(func):
'''
accepts_scalar_input is a decorator which expects to be used on class
methods. It lets the user pass either a vector or a scalar to a function,
as long as the function treats everything like a vector. Input and output is
sanatized to the user expected format on return.
'''
@ignores_exc_tb
@wraps(func)
def wrapper_vec_output(self, input_, *args, **kwargs):
is_scalar = not isiterable(input_)
if is_scalar:
iter_input = (input_,)
else:
iter_input = input_
result = func(self, iter_input, *args, **kwargs)
if is_scalar:
if len(result) != 0:
result = result[0]
return result
return wrapper_vec_output

编辑:用于重新引发异常的新 python 3 语法:


exc_type, exc_value, exc_traceback = sys.exc_info()
尝试:
exc_traceback = exc_traceback.tb_next
exc_traceback = exc_traceback.tb_next
除了异常:
经过
ex = exc_type(exc_value)
ex.__traceback__ = exc_traceback
抚养前任

关于python - 可以从 Python 异常回溯中删除装饰器吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22825165/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com