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
...
Hi all,
can someone say why this is stuck in a infinite loop?
while True:
print("why is this happening")
try:
break
finally:
continue
why is this happening
why is this happening
why is this happening
...
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?
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
finallyclause executes areturn,breakorcontinuestatement, the saved exception is discarded:
And
When a
return,breakorcontinuestatement is executed in thetrysuite of atryâŚfinallystatement, thefinallyclause is also executed âon the way out.â
The return value of a function is determined by the lastreturnstatement executed.
But I donât think anyone would mind if you suggest an improvement of the docs there.
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
breakpasses control out of atrystatement with afinallyclause, thatfinallyclause 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
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 ![]()
You can probably check the changelog of 3.8 and from there search back through the PRs/issues.
check this documentation link
I would look at it this way: there is a virtual program counter that determines which statement is executed next. The value of this counter isnât actually used until it is time to determine what to next execute, which doesnât happen until the finally clause executes. Thus, in a sense, continue overwrites the value written by break before the value of the program counter is requested.
That is, the break statement says âSet the program counter to 7â, but before you actually go to line 7, you have to execute continue, which says âSet the program counter to line 2â. Now that the try statement is complete, you look at the program counter to see where to go next, and the program counter is set to 2.
That is consistent with the result of unwrapping the loop into (infinitely many prints, followed by infinitely many break)
print("why is this happening")
print("why is this happening")
print("why is this happening")
...
break
break
break
...
We get this (\omega\cdot 2)-list of instructions, since each finally does a continue âbefore leaving the loopâ. So, all passes over the loopâs code get done before all the âleaving of the loopâ.