Reputation: 2630
The following code raises a syntax error:
>>> for i in range(10):
... print i
... try:
... pass
... finally:
... continue
... print i
...
File "<stdin>", line 6
SyntaxError: 'continue' not supported inside 'finally' clause
Why isn't a continue
statement allowed inside a finally
clause?
P.S. This other code on the other hand has no issues:
>>> for i in range(10):
... print i
... try:
... pass
... finally:
... break
...
0
If it matters, I'm using Python 2.6.6.
Upvotes: 43
Views: 6757
Reputation: 1776
Now this feature is available with the release of 3.8
https://docs.python.org/3/whatsnew/3.8.html
Sample Code
def new_f():
for i in range(0,24):
try:
print(1/0)
except:
print('In Exception')
finally:
print('In finally')
continue
Upvotes: -1
Reputation: 362945
A continue statement was illegal in the finally clause due to a problem with the implementation. In Python 3.8 this restriction was lifted.
The bug was issue32489 - Allow 'continue' in 'finally' clause.
The pull request for the fix: https://github.com/python/cpython/pull/5822
Upvotes: 6
Reputation:
The possibility of getting an exception raised and then just swallowed because you're using a continue
is a strong argument, but the exception is also swallowed when you use a break
or return
instead.
For example, this works and the exception is swallowed:
for i in range(10):
print i
try:
raise Exception
finally:
break
print i # not gonna happen
This again works with no error (when in a function) and the exception is swallowed too:
for i in range(10):
print i
try:
raise Exception
finally:
return
print i # not gonna happen
So why would break
and return
be allowed in a finally
block, with or without possible raised errors, but continue
not?
You might also consider the combination of the following factors in the issue:
finally
is always executed;continue
"aborts" the current iteration.This will mean that inside each loop, because of the finally
always executing, you will always have a continue
witch basically
says "abort current iteration", "abort current iteration", "abort current iteration" ... witch doesn't really make any sense. But it doesn't make sense either to use break
and return
. The current iteration is also aborted with the only difference
that you now end up with just one iteration.
So the question "Why is continue
not allowed in a finally
?" can also be asked as "Why is break
and return
allowed?".
Maybe because it made sense not to at that point? It was the developers decision and now its like it is? Sure, it might also be implementor's laziness but who knows, maybe they had something in mind and perhaps, in another version of Python, it would make more sense to have it another way?
The idea is that the examples here are just extreme. You don't just write code like that, do you? There is sure to be some
logic in the finally
block to say when to break/return/continue
, whatever, and not just have it blunt like that. As such, IMHO continue
inside a finally
should be allowed because I would appreciate writing a clean code with using continue
in finally
if that's what I need, instead of resorting to a code workaround for this limitation (i.e. in Python's philosophy "We're all consenting adults here").
Upvotes: 2
Reputation: 33716
I didn't see it mentioned in another response, but I think what you might want in this case is try..else
:
for i in range(10):
print i
try:
#pass <= I commented this out!
do_something_that_might_fail(i)
except SomeException:
pass
else:
continue
print i
The else
block is only executed if there was no exception. So what this means is:
print i
try
to do_something_that_might_fail(i)
SomeException
, fall through and print i
againcontinue
(and i
is never printed)Upvotes: 2
Reputation: 226456
The use of continue in a finally-clause is forbidden because its interpretation would have been problematic. What would you do if the finally-clause were being executed because of an exception?
for i in range(10):
print i
try:
raise RuntimeError
finally:
continue # if the loop continues, what would happen to the exception?
print i
It is possible for us to make a decision about what this code should do, perhaps swallowing the exception; but good language design suggests otherwise. If the code confuses readers or if there is a clearer way to express the intended logic (perhaps with try: ... except Exception: pass; continue
), then there is some advantage to leaving this as a SyntaxError.
Interestingly, you can put a return inside a finally-clause and it will swallow all exceptions including KeyboardInterrupt, SystemExit, and MemoryError. That probably isn't a good idea either ;-)
Upvotes: 25
Reputation: 6966
I think the reason for this is actually pretty simple. The continue statement after the finally keyword is executed every time. That is the nature of the finally statement. Whether or not your code throws an exception is irrelevant. Finally will be executed.
Therefore, your code...
for i in range(10):
print i
try:
pass
finally:
continue
print i # this (and anything else below the continue) won't ever be executed!
is equivalent to this code...
for i in range(10:
print i
try:
pass
finally:
pass
which is cleaner and terser. Python does not allow continue in a finally block because all code after the continue will never be executed. (Sparse is better than dense.)
Upvotes: 2
Reputation: 34334
The Python Language Reference forbids the use of continue
within a finally
clause. I'm not entirely sure why. Perhaps because continue
within the try
clause ensures that the finally
is executed, and deciding what continue
should do within the finally
clause is somewhat ambiguous.
Edit: @Mike Christensen's comment to the question points out a thread where this construction's ambiguity is discussed by Python core developers. Additionally, in more than nine years of Python use, I've never wanted to do this, so it's probably a relatively uncommon situation that developers don't feel like spending much time on.
Upvotes: 6