Michael Scheper
Michael Scheper

Reputation: 7118

Reraising an exception so it's handled in the same block

I have code that's a bit like this:

try:
    # do stuff
except SomeSpecificException as sse:
    if sse.some_property == some_special_value:
        # handle the exception in a special way
    else:
        handle_exception_normally()
except:
    handle_exception_normally()

I want to catch the specific exception and handle it in a special way, but only if it has a particular property. If it doesn't have that property, I want it to be handled just like any other exception (logging, screaming, etc.)

The code above works, but if possible, I want to avoid repeating handle_exception_normally() (DRY and all that).

Just putting raise in the else clause of the first except block does not work. A parent try block would catch that, but the catch-all clause in the same block will not.

I could nest two try blocks, but it's not very elegant; I'd rather just use the code I have above.

Is there a better way?

Note that I'm using Python 3.

Upvotes: 2

Views: 99

Answers (2)

Rick
Rick

Reputation: 45291

I understand OP said they do not want to do this, but I'm throwing my lot in with the nested try block. I think it's the most readable way to go about this:

try:
    try:
        # do stuff
    except SomeSpecificException as sse:
        if sse.some_property == some_special_value:
            # handle the exception in a special way
        else:
            raise
except:
    handle_exception_normally()

Upvotes: 0

Fabien
Fabien

Reputation: 4972

I would opt for:

try:
    # do stuff
except Exception as e:
    if e.args[0] == 'Discriminate Exception Here' and sse.some_property == some_special_value:
        # handle the exception in a special way
    else:
        handle_exception_normally()

Moses Koledoye proposed:

try:
    # do stuff
except Exception as e:
    if getattr(e, 'some_property', None) == some_special_value:
        # handle the exception in a special way
    else:
        handle_exception_normally()

Which is shorter but requires some_special_value to always be != None and attribute to be unique to your exception.

Examples of exception discrimination, with e.args[0]:

try:
 5 / 0
except Exception as e:
 print(e.args[0])

division by zero

With __class__.__name__:

try:
 5 / 0
except Exception as e:
 print(e.__class__.__name__)

ZeroDivisionError

With isinstance() (bit more CPU intensive) :

try:
 5 / 0
except Exception as e:
 isinstance(e, ZeroDivisionError)

True

Upvotes: 5

Related Questions