kasperd
kasperd

Reputation: 2052

Can a finally block know if there was an exception

In a Python program I have code with the following structure:

try:
    value = my_function(*args)
finally:
    with some_context_manager:
        do_something()
        if 'value' in locals():
            do_something_else(value)

But the 'value' in locals() construction feels a bit fragile and I am wondering if there is a better way to do this.

What I really want is for the code inside the finally to behave slightly different depending on whether the try block raised an exception. Is there a way to know if an exception was raised?

Upvotes: 5

Views: 2335

Answers (3)

wwii
wwii

Reputation: 23763

Assign the exception to a variable in the except suite then use it in the finally suite.

foo = False
try:
    raise KeyError('foo not found')
except KeyError as e:
    pprint(e)
    foo = e
finally:
    if foo:
        print(foo)
    else:
        print('NO')

Upvotes: -1

clutton
clutton

Reputation: 640

Here are a couple ideas:

Set value before attempting the try:

value = None
try:
    value = my_function(*args)
finally:
    with some_context_manager:
        do_something()
        if value is not None:
            do_something_else(value)

Or if you want to set the value based on the exception type:

try:
    value = my_function(*args)
except:
    value = None
    raise
finally:
    with some_context_manager:
        do_something()
        if value is not None:
            do_something_else(value)

Upvotes: 1

mwchase
mwchase

Reputation: 811

If the goal is "when an exception was raised, do something different", how about:

exception_raised = False
try:
    value = my_function(*args)
except:
    exception_raised = True
    raise
finally:
    with some_context_manager:
        do_something()
        if not exception_raised:
            do_something_else(value)

Now, if you're going to have multiple exceptions that you actually do something with, I'd recommend:

completed_successfully = False
try:
    value = my_function(*args)
else:
    completed_successfully = True
finally:
    with some_context_manager:
        do_something()
        if completed_sucessfully:
            do_something_else(value)

Upvotes: 3

Related Questions