removed from the block stack.
It is similar to :opcode:`END_FINALLY`, but doesn't change the bytecode
- counter nor raise an exception. Used for implementing :keyword:`break`
- and :keyword:`return` in the :keyword:`finally` block.
+ counter nor raise an exception. Used for implementing :keyword:`break`,
+ :keyword:`continue` and :keyword:`return` in the :keyword:`finally` block.
.. versionadded:: 3.8
is executed. If there is a saved exception it is re-raised at the end of the
:keyword:`finally` clause. If the :keyword:`finally` clause raises another
exception, the saved exception is set as the context of the new exception.
-If the :keyword:`finally` clause executes a :keyword:`return` or :keyword:`break`
-statement, the saved exception is discarded::
+If the :keyword:`finally` clause executes a :keyword:`return`, :keyword:`break`
+or :keyword:`continue` statement, the saved exception is discarded::
>>> def f():
... try:
When a :keyword:`return`, :keyword:`break` or :keyword:`continue` statement is
executed in the :keyword:`try` suite of a :keyword:`try`...\ :keyword:`finally`
-statement, the :keyword:`finally` clause is also executed 'on the way out.' A
-:keyword:`continue` statement is illegal in the :keyword:`finally` clause. (The
-reason is a problem with the current implementation --- this restriction may be
-lifted in the future).
+statement, the :keyword:`finally` clause is also executed 'on the way out.'
The return value of a function is determined by the last :keyword:`return`
statement executed. Since the :keyword:`finally` clause always executes, a
and information on using the :keyword:`raise` statement to generate exceptions
may be found in section :ref:`raise`.
+.. versionchanged:: 3.8
+ Prior to Python 3.8, a :keyword:`continue` statement was illegal in the
+ :keyword:`finally` clause due to a problem with the implementation.
+
.. _with:
.. _as:
continue_stmt: "continue"
:keyword:`continue` may only occur syntactically nested in a :keyword:`for` or
-:keyword:`while` loop, but not nested in a function or class definition or
-:keyword:`finally` clause within that loop. It continues with the next
-cycle of the nearest enclosing loop.
+:keyword:`while` loop, but not nested in a function or class definition within
+that loop. It continues with the next cycle of the nearest enclosing loop.
When :keyword:`continue` passes control out of a :keyword:`try` statement with a
:keyword:`finally` clause, that :keyword:`finally` clause is executed before
Other Language Changes
======================
+* A :keyword:`continue` statement was illegal in the :keyword:`finally` clause
+ due to a problem with the implementation. In Python 3.8 this restriction
+ was lifted.
+ (Contributed by Serhiy Storchaka in :issue:`32489`.)
+
* Added support of ``\N{name}`` escapes in :mod:`regular expressions <re>`.
(Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.)
"""
self.check_stack_size(snippet)
- def test_for_break_inside_finally_block(self):
+ def test_for_break_continue_inside_finally_block(self):
snippet = """
for x in y:
try:
finally:
if z:
break
+ elif u:
+ continue
else:
a
else:
else:
self.fail("failed to get expected SyntaxError")
- s = '''while 1:
- try:
- pass
- finally:
- continue'''
-
- if not sys.platform.startswith('java'):
- ckmsg(s, "'continue' not supported inside 'finally' clause")
-
s = '''if 1:
try:
continue
break
self.assertEqual(count, 0)
+ def test_continue_in_finally(self):
+ count = 0
+ while count < 2:
+ count += 1
+ try:
+ pass
+ finally:
+ continue
+ break
+ self.assertEqual(count, 2)
+
+ count = 0
+ while count < 2:
+ count += 1
+ try:
+ break
+ finally:
+ continue
+ self.assertEqual(count, 2)
+
+ count = 0
+ while count < 2:
+ count += 1
+ try:
+ 1/0
+ finally:
+ continue
+ break
+ self.assertEqual(count, 2)
+
+ for count in [0, 1]:
+ try:
+ pass
+ finally:
+ continue
+ break
+ self.assertEqual(count, 1)
+
+ for count in [0, 1]:
+ try:
+ break
+ finally:
+ continue
+ self.assertEqual(count, 1)
+
+ for count in [0, 1]:
+ try:
+ 1/0
+ finally:
+ continue
+ break
+ self.assertEqual(count, 1)
+
def test_return_in_finally(self):
def g1():
try:
>>> test()
9
-Start simple, a continue in a finally should not be allowed.
+continue in a finally should be ok.
>>> def test():
... for abc in range(10):
... pass
... finally:
... continue
- Traceback (most recent call last):
- ...
- SyntaxError: 'continue' not supported inside 'finally' clause
-
-This is essentially a continue in a finally which should not be allowed.
+ ... print(abc)
+ >>> test()
+ 9
>>> def test():
... for abc in range(10):
... continue
... except:
... pass
- Traceback (most recent call last):
- ...
- SyntaxError: 'continue' not supported inside 'finally' clause
+ ... print(abc)
+ >>> test()
+ 9
+
+ >>> def test():
+ ... for abc in range(10):
+ ... try:
+ ... pass
+ ... finally:
+ ... try:
+ ... pass
+ ... except:
+ ... continue
+ ... print(abc)
+ >>> test()
+ 9
+
+A continue outside loop should not be allowed.
>>> def foo():
... try:
... continue
Traceback (most recent call last):
...
- SyntaxError: 'continue' not supported inside 'finally' clause
-
- >>> def foo():
- ... for a in ():
- ... try:
- ... pass
- ... finally:
- ... continue
- Traceback (most recent call last):
- ...
- SyntaxError: 'continue' not supported inside 'finally' clause
-
- >>> def foo():
- ... for a in ():
- ... try:
- ... pass
- ... finally:
- ... try:
- ... continue
- ... finally:
- ... pass
- Traceback (most recent call last):
- ...
- SyntaxError: 'continue' not supported inside 'finally' clause
-
- >>> def foo():
- ... for a in ():
- ... try: pass
- ... finally:
- ... try:
- ... pass
- ... except:
- ... continue
- Traceback (most recent call last):
- ...
- SyntaxError: 'continue' not supported inside 'finally' clause
+ SyntaxError: 'continue' not properly in loop
There is one test for a break that is not in a loop. The compiler
uses a single data structure to keep track of try-finally and loops,
--- /dev/null
+A :keyword:`continue` statement is now allowed in the :keyword:`finally`
+clause.
ADDOP_JABS(c, JUMP_ABSOLUTE, info->fb_block);
return 1;
}
- if (info->fb_type == FINALLY_END) {
- return compiler_error(c,
- "'continue' not supported inside 'finally' clause");
- }
if (!compiler_unwind_fblock(c, info, 0))
return 0;
}