Reputation: 678
I am experimenting with Python Decorators in order to understand what it happening and I have hit a head-scratcher.
My code is this (python 2.7.6):
import traceback
def dec(func):
def wrapped(*args, **kwargs):
try:
if flag:
print 'flagged'
else:
print 'unflagged'
except NameError as e:
print 'error?'
raise
finally:
return func(*args, **kwargs)
return wrapped
@dec
def foo(x):
print x
foo(3)
when run, the output is:
error?
3
I expected that calling foo(3) would raise:
NameError: global name 'flag' is not defined
Why is the "raise" not raising? Clearly, the error is caught - the print from the Except block is executed...
Upvotes: 2
Views: 1442
Reputation: 280898
The return
in the finally
overrides and cancels any exception or function return that might have triggered the finally
block. This is documented in the Python Language Reference:
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 or executes areturn
orbreak
statement, the saved exception is discarded:
For example:
def f():
try:
1/0
finally:
return
f() # No exception
def g():
try:
return 1
finally:
return 0
g() # 0
def h():
try:
raise NameError
finally:
raise TypeError
h() # TypeError
Upvotes: 1