Jump statement in try except finally block

Hi all,
can someone say why this is stuck in a infinite loop?

Code

while True:
    print("why is this happening")
    try:
        break
    finally:
        continue

Output

why is this happening
why is this happening
why is this happening
...
2 Likes

Because control flow statements (break, continue, return, raise) in finally suites overwrite whatever else would have happened if executed. This is almost always a bad idea and will lead to confusing code.

Is that documented somewhere?

Yes: 8. Compound statements — Python 3.12.4 documentation

That’s of course where I had immediately looked. Where there exactly is this behavior documented? I don’t see it.

This exact edge case is not directly listed. IMO it follows well enough from

If the finally clause executes a return, break or continue statement, the saved exception is discarded:

And

When a return, break or continue statement is executed in the try suite of a tryfinally statement, the finally clause is also executed ‘on the way out.’
The return value of a function is determined by the last return statement executed.

But I don’t think anyone would mind if you suggest an improvement of the docs there.

4 Likes

I had seen all that and I disagree that any of that documents this case. The ‘on the way out’ even rather sounds like the opposite to me.

Good, then we disagree. Go propose a change if you care.

Maybe combining with this sentence in the documentation of break

When break passes control out of a try statement with a finally clause, that finally clause is executed before really leaving the loop.

I guess one can think, or not, that the breaks get queued for execution after the finally is done. The effect is the same, the break would only happen after the loop completes, which in this case is never.

FWIW, it works the same way in other languages that have the same suite of try, finally etc. keywords.

Similar to the “on the way out”, to me that rather sounds like the “leaving the loop” is still happening. Otherwise it’d be “instead of really leaving the loop” in this case. I think it’s just not clear either way. Unlike the double return, which is explicitly and clearly covered:

The return value of a function is determined by the last return statement executed. Since the finally clause always executes, a return statement executed in the finally clause will always be the last one executed: [example]

‘on the way out’ of try, not the loop :rofl: it’s all there

What’s the point of repeating that as if we hadn’t discussed it already?

sorry, I must have missed some of it, I was just curious about the implementation problem prior to 3.8 ? Is that outside this post :woozy_face:

You can probably check the changelog of 3.8 and from there search back through the PRs/issues.