I want to keep a track of exceptions inside a dictionary and return the same. However when I do so, finally block gives me an empty dictionary. The logic pretty much works for scalars. Can someone explain the behavior please.
In scalar context:
def test():
temp = 1
try:
raise ValueError("sdfs")
except:
temp = 2
finally:
temp = temp + 3
return temp
test()
5
With dictionary:
def test():
temp = dict()
try:
raise ValueError("something")
except Exception as error:
print("error is :{}".format(error))
temp['except'] = "something" + error
finally:
return temp
test()
error is : something
{}
You caused another exception to be raised in the exception handler, which is swallowed because there is a finally
handler that returns from the function.
You can't just concatenate an exception object and a string, so an additional TypeError
is raised, and the assignment to the dictionary is never reached.
Converting the exception to a string first works:
>>> def test():
... temp = dict()
... try:
... raise ValueError("something")
... except Exception as error:
... print("error is :{}".format(error))
... temp['except'] = "something" + str(error)
... finally:
... return temp
...
>>> test()
error is :something
{'except': 'somethingsomething'}
From the try
statement documentation:
If
finally
is present, it specifies a ‘cleanup’ handler. Thetry
clause is executed, including anyexcept
andelse
clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. Thefinally
clause is executed. If there is a saved exception it is re-raised at the end of thefinally
clause. If thefinally
clause raises another exception, the saved exception is set as the context of the new exception. If thefinally
clause executes areturn
orbreak
statement, the saved exception is discarded[.]
(Bold emphasis mine).
The line "something" + error
raises an error which is discarded because you returned from finally
. Due to the error the assignment to the dictionary temp
is never performed giving the impression that nothing happens.
This is stated in the documentation for try-except
:
If finally is present, it specifies a ‘cleanup’ handler. The
try
clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception it is re-raised at the end of the finally clause. If the finally clause raises another exception, the saved exception is set as the context of the new exception. If the finally clause executes a return or break statement, the saved exception is discarded.
(Emphasis mine)
Without an error (i.e temp['except'] = error
you get the expected behavior:
>>> test()
error is :something
{'except': ValueError('something')}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With