This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author fov
Recipients fov
Date 2014-12-03.17:51:13
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
This bug report is the opposite of issue #14718. The interpreter did not raise an error when it encountered a `yield` expression inside the `finally` part of a `try/finally` statement.

My system's info: Python 3.4.2 (v3.4.2:ab2c023a9432, Oct  6 2014, 22:15:05) [MSC v.1600 32 bit (Intel)] on win32

More detail

My interpreter does not raise any errors when yielding from a `finally` block. The documentation states, "Yield expressions are allowed in the try clause of a try ... finally construct."[1] Though not explicitly stated, the suggestion is that `yield` is not allowed in the `finally` clause. Issue #14718 suggests that this interpretation is correct.

Not raising an exception for `yield` inside of `finally` can cause incorrect behavior when the generator raises its own unhandled exception in the `try` block. PEP 342 says, "If the generator raises an uncaught exception, it is propagated to send()'s caller." In this case, however, the exception gets paused at the `yield` expression, instead of propagating to the caller. 

Here's an example that can clarify the issue:

>>> def f():  # I expected this function not to compile
...     try:
...         raise ValueError
...     finally:
...         yield 1  # Execution freezes here instead of propagating the ValueError
...     yield "done"
>>> g = f()
>>> g.send(None)  # PEP 342 would require ValueError to be raised here
>>> g.send(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in f2

I may be arguing over the meaning of "uncaught exception," but I expected (given that the function compiles and doesn't raise a `RuntimeError`) the `ValueError` to propagate rather than get frozen.

Example 2

The second example is adapted from, where the submitter received a `RuntimeError`, but I did not:

>>> def f2():  # I also expected this function not to compile
...   try:
...     yield 1
...   finally:
...     yield 4
>>> g = f()  # issue 14718 suggests this should raise RuntimeError
>>> next(g)
>>> next(g)
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>

Possible resolution:

1. Enforce the ban on `yield` inside a finally `clause`. It seems like this should 
   already be happening, so I'm not sure why my version isn't performing the check.
   This could be a run-time check (which seems like it may already be implemented),
   but I think this could even be a compile-time check (by looking at the AST).
2. Clarify the documentation to make explicit the ban on the use of `yield` inside
   the `finally` clause, and specify what type of error it will raise (i.e., 
   `SyntaxError` or `RuntimeError`? or something else?).

I'll submit a patch for 2 if there's support for this change, and I will work on 1 if someone can point me in the right direction. I've engaged with the C source relating to the different protocols, but have never looked through the compiler/VM.

Date User Action Args
2014-12-03 17:51:14fovsetrecipients: + fov
2014-12-03 17:51:14fovsetmessageid: <>
2014-12-03 17:51:14fovlinkissue22988 messages
2014-12-03 17:51:13fovcreate