0

My code tries to do something, but it triggers an Error... which triggers another Error. So, the error message looks something like this:

SillyError: you can`t do that becuz blablabla

The above exception was the direct cause of the following exception:

LoopyError: you can`t do that becuz blobloblo 

I want to create a try except block that only catches this specific duo of errors. However, I am only able to catch the first one, because once I do, the second one never gets a chance to trigger.

This other question is about catching either exception, but I want to catch only if both are triggered in succession. Is there a way?

colorlace
  • 816
  • 2
  • 10
  • 17

1 Answers1

2

If you have a try\except, you will always catch the error based on the outer exception. However you do have the option to pass on any exceptions you don't want to process.

In this code, the ZeroDivisionError is caught and wrapped in another exception which is then caught by the calling code. The calling code checks for the inner exception and decides whether to re-raise the exception up the stack.

def xtest():
    try:
        a = 1/0  # exception - division by zero
    except ZeroDivisionError as e:
        raise Exception("Outer Exception") from e  # wrap exception (e not needed for wrap)

try:
   xtest()
except Exception as ex:
   print(ex)  # Outer Exception
   print(ex.__cause__)  # division by zero
   
   if (str(ex) == "Outer Exception" and str(ex.__cause__) == "division by zero"):
       print("Got both exceptions")
   else:
       raise # pass exception up the stack

Just for completion, you can do the check based on the exception class name also:

   if (type(ex).__name__ == "Exception" and type(ex.__cause__).__name__ == "ZeroDivisionError"):
       print("Got both exceptions")

@ShadowRanger pointed out that it may be quicker to just check the class type instead of the class name:

   if (type(ex) == Exception and type(ex.__cause__) == ZeroDivisionError):
       print("Got both exceptions")
Mike67
  • 11,175
  • 2
  • 7
  • 15
  • 1
    `from e` isn't necessary inside an `except` block when you want to wrap the exception you just caught; the wrapping occurs automatically. You only need `from e` if there is some *other* exception (not the one you're currently handling) that you want to wrap, or use `from None` to suppress the automatic wrapping. – ShadowRanger Jul 31 '20 at 02:44
  • 1
    Also, I'd avoid using `.__name__` in favor of just `if type(ex) is Exception and type(ex.__cause__) is ZeroDivisionError:`; there's no need to compare strings when you can just verify the type directly with less typing and less work. – ShadowRanger Jul 31 '20 at 02:46