-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
Python 3.12.0a7 can fail to catch exceptions when an iterator is involved #103488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Verified on latest 3.11/2 releases on Windows. |
Line 12 being in the traceback instead of line 10 also seems wrong. |
If |
@mattclay Inserting |
Can you post the reduced reproducer? And maybe the code object disassembly ( |
@gvanrossum Who is 'who'? I reduced the raise and catch a bit but also added 3 debug prints to trace execution. |
I simplified the reproducer a bit using the suggestion from @terryjreedy: #!/usr/bin/env python
def do_work():
yield
x
def main():
try:
for _ in do_work():
if True is False:
return
except NameError:
pass
if __name__ == '__main__':
main() I've also attached the code object disassembly from Python 3.11 and 3.12 for the revised reproducer. dis311.txt |
It seems like this symptom could also result from a change in the timing of finalization of the |
The change in behavior bisects to 4a1c58d cc @markshannon |
The conditional statement, a 'complex*' condition evaluating to false, so that the body is not executed, and a break/return in the non-executed body, seem necessary to get the error. |
Here's an even shorter reproducer: def do_work():
yield
x
try:
for _ in do_work():
if True is False:
break
except NameError:
pass Here's the dis311-simple.txt (3.11.3) |
Note the bisect blame commit doesn't change the compiler, so it's not an issue in the bytecode (unless it was a latent issue from earlier that was then exposed by a runtime change), it's something in the runtime behavior of generators changed in that commit. I confirmed that the |
It does appear, though, that the issue is that we fall into a hole in the exception table; the instruction offset used when calling Repro code I'm usingdef do_work():
yield
x
try:
for _ in do_work():
if True is False:
break
except NameError:
pass Bytecode
|
* Use return-offset, not yield-offset, so that instruction pointer is correct when sending to a generator or coroutine.
* main: pythongh-103479: [Enum] require __new__ to be considered a data type (pythonGH-103495) pythongh-103365: [Enum] STRICT boundary corrections (pythonGH-103494) pythonGH-103488: Use return-offset, not yield-offset. (pythonGH-103502) pythongh-103088: Fix test_venv error message to avoid bytes/str warning (pythonGH-103500) pythonGH-103082: Turn on branch events for FOR_ITER instructions. (python#103507) pythongh-102978: Fix mock.patch function signatures for class and staticmethod decorators (python#103228) pythongh-103462: Ensure SelectorSocketTransport.writelines registers a writer when data is still pending (python#103463) pythongh-95299: Rework test_cppext.py to not invoke setup.py directly (python#103316)
I've verified the issue has been resolved. I tested with the deadsnakes nightly build (commit 1aa376f). |
Bug report
Python 3.12.0a7 (at least as of commit d65ed69) can fail to catch exceptions when an iterator is involved. The following code works on Python 3.11 but the
ValueError
is uncaught on Python 3.12:With this code in
repro.py
the following traceback is shown on Python 3.12:No error or output occurs under Python 3.11.
Your environment
Tested on Ubuntu 20.04.5 using the deadsnakes nightly build: python3.12 - 3.12.0~a7-98-gd65ed693a8-1+focal1
Linked PRs
The text was updated successfully, but these errors were encountered: