Consider:
def raiseMe( text="Test error" ):
raise Exception( text )
def break_in_finally_test():
for i in range(5):
if i==2:
try:
raiseMe()
except:
raise
else:
print "succeeded!"
finally:
print "testing this!"
break
if __name__=='__main__':
break_in_finally_test()
I expected to see Exception( "Test error" )
to be raised, but instead only "testing this" is printed. The intention, of course, was to call raiseMe()
only once, no matter if we succeed or not - but if it raises an exception, I would have wanted to see that!
Why does break swallow the exception that I explicitly raise?
UPDATE: from Python3.14 onwards, using break
, continue
or return
in a finally
clause will trigger a SyntaxWarning
(PEP765)
From https://docs.python.org/2.7/reference/compound_stmts.html#finally:
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 or executes a return or break statement, the saved
exception is discarded
This also reflects the behaviour expected from the try...finally
statement before PEP341:
This is how a try except finally block looked like pre PEP341:
try:
try:
raiseMe()
except:
raise
finally:
#here is where cleanup is supposed to happen before raising error
break
#after finally code: raise error
As the raising of errors never happens in the finally
block it is never actually raised.
To maintain backwards compatibility with Python<=2.4, it had to be done in this way.