在 Python 中实现重试时创建常规异常类

正如标题所解释的那样,我想创建一个常规异常类,以从内置的异常类继承,这些异常类稍后将在其他类中捕获。


这是我的代码:


from functools import wraps



class ControlledException(TypeError, AttributeError):

    """A generic exception on the program's domain."""



class WithRetry:

    def __init__(self, retries_limit=3, allowed_exceptions=None):

        self.retries_limit = retries_limit

        self.allowed_exceptions = allowed_exceptions or (ControlledException,)


    def __call__(self, operation):

        @wraps(operation)

        def wrapped(*args, **kwargs):

            last_raised = None


            for _ in range(self.retries_limit):

                try:

                    return operation(*args, **kwargs)

                except self.allowed_exceptions as e:

                    print(f'retrying {operation.__qualname__} due to {e}')

                    last_raised = e

            raise last_raised


        return wrapped



@WithRetry()

def test(x):

    x = x + 1

    print(x)



test('a')

ControlledExceptionclass 继承了两个异常,我想捕获它们。在这种情况下,程序将捕获 .TypeErrorAttributeErrorTypeError


我不知道为什么这个参数对(ControlledException,)没有影响。但是,如果我将(ControlledException,)更改为“异常”或“类型错误”,则会捕获错误。self.allowed_exceptions


汪汪一只猫
浏览 63回答 1
1回答

动漫人物

定义此类自定义异常时,要么必须直接使用它们,要么必须捕获原始异常,然后引发自定义异常。raise在这里,我捕获了原始异常,抑制了它们的回溯并引发了自定义异常。from functools import wrapsclass ControlledException(TypeError, AttributeError):&nbsp; &nbsp; """A generic exception on the program's domain."""class WithRetry:&nbsp; &nbsp; def __init__(self, retries_limit=3, allowed_exceptions=None):&nbsp; &nbsp; &nbsp; &nbsp; self.retries_limit = retries_limit&nbsp; &nbsp; &nbsp; &nbsp; self.allowed_exceptions = allowed_exceptions or (ControlledException,)&nbsp; &nbsp; def __call__(self, operation):&nbsp; &nbsp; &nbsp; &nbsp; @wraps(operation)&nbsp; &nbsp; &nbsp; &nbsp; def wrapped(*args, **kwargs):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for _ in range(self.retries_limit):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return operation(*args, **kwargs)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # if you want to catch the error, you have to catch the original&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # exceptions as opposed to custom exceptions&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; except (TypeError, AttributeError) as exc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(f"retrying {operation.__qualname__} due to {exc}")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # this suppresses the original error message and raises your&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # custom exception&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise ControlledException("Here is your error message!!") from None&nbsp; &nbsp; &nbsp; &nbsp; return wrapped@WithRetry()def test(x):&nbsp; &nbsp; x = x + 1&nbsp; &nbsp; print(x)test("a")这将打印出来:retrying test due to can only concatenate str (not "int") to str---------------------------------------------------------------------------ControlledException&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Traceback (most recent call last)<ipython-input-364-2a7d6eb73e92> in <module>&nbsp; &nbsp; &nbsp;38&nbsp;&nbsp; &nbsp; &nbsp;39&nbsp;---> 40 test('a')<ipython-input-364-2a7d6eb73e92> in wrapped(*args, **kwargs)&nbsp; &nbsp; &nbsp;27&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# this suppresses the original error message and raises your&nbsp; &nbsp; &nbsp;28&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# custom exception---> 29&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;raise ControlledException('Here is your error message!!') from None&nbsp; &nbsp; &nbsp;30&nbsp;&nbsp; &nbsp; &nbsp;31&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return wrappedControlledException: Here is your error message!!
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python