New submission from Felipe: 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 1 >>> g.send(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in f2 ValueError 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 http://bugs.python.org/issue14718, 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) 1 >>> next(g) 4 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration 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. Notes ============================================ [1] https://docs.python.org/3.4/reference/expressions.html#yield-expressions ---------- components: Interpreter Core messages: 232081 nosy: fov priority: normal severity: normal status: open title: No error when yielding from `finally` type: behavior versions: Python 3.4 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue22988> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com