-
-
Notifications
You must be signed in to change notification settings - Fork 30.5k
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
PEP 669: for loop fires LINE multiple times for body, but only one for for
#104239
Comments
Perhaps because iteration jumps into the middle of the bytecode for the header line, and line events only trigger on the first bytecode of the line. To me, "LINE: An instruction is about to be executed that has a different line number from the preceding instruction." can reasonably be interpreted the way you expected. But I am not sure what 'instruction' means in this context. "bytecode" is specific to CPython and the feature is not meant to be so limited. We need a draft code addition in order to ask such questions. Anyway, I am glad to see a specific example of monitoring in use. |
The disassembly looks like this: Disassembly of <code object loop3 at 0x1011f7cc0, file "loop3.py", line 3>:
3 0 RESUME 0
4 2 LOAD_GLOBAL 1 (NULL + range)
12 LOAD_CONST 1 (3)
14 CALL 1
22 GET_ITER
>> 24 FOR_ITER 13 (to 54)
28 STORE_FAST 0 (i)
5 30 LOAD_GLOBAL 3 (NULL + print)
40 LOAD_FAST 0 (i)
42 CALL 1
50 POP_TOP
52 JUMP_BACKWARD 15 (to 24)
4 >> 54 END_FOR
6 56 LOAD_GLOBAL 3 (NULL + print)
66 LOAD_CONST 2 ('done')
68 CALL 1
76 POP_TOP
78 RETURN_CONST 0 (None) Line 5 ends with a JUMP_BACKWARD to 24, which is in line 4, so shouldn't it call the line callback again? |
I believe only the first instruction on each line is instrumented as You can use I would guess @markshannon expected the tools to handle this with |
I don't understand: why do I get three events for line 5? |
By the hypothesis of me and Tian, because the first bytecode of line 5, the load global of 'print', (and as Tian added, INSTRUMENTED_LINE) is executed 3 times. |
If that is correct, and the behavior I'm seeing is expected, then the PEP needs to be updated:
|
"Preceding" here means the instruction immediately before it in the code object, not the instruction previously executed. The Because the jump at the end of line 5 jumps into the middle of line 4, there is only one "line 4" event. |
I thought that debuggers would use the LINE event to step by lines, but maybe I misunderstood. If they did, stepping wouldn't behave properly, because I'd expect a debugger to visit line 4 a number of times. |
Maybe we could trigger LINE events for any instruction that has any predecessor with a different line number. We also need to maintain the behavior of @fabioz any thoughts on this? |
IDLE's bdb-based debugger on 3.12.0a7 stops 4 times on line 4 (3 + 1 for Stopping) and 3 times for line 5. I presume stepping in pdb, also based on bdb, does the same. A new debugger should continue stopping on the header line when stepping. This is even more important for while loops, where one might want to see local values to debug the loop condition. |
I agree that we should stop at the |
I think that whenever the line changes (regardless of being marked as the entry point of the line or not) the line event should be triggered (which I guess is mostly what happens with the current sys.settrace, where I guess the logic worked reasonably). The best place for that logic is probably inside the new monitoring mechanism, otherwise all clients will probably end up having to do some workarounds which would probably be more costly than what can be done inside of the new monitoring code (I'm not even sure what'd be the workaround for clients at this point, maybe doing additional bookeping using both the LINE as well as the JUMP and BRANCH and then deciding whether it changed -- but it seems more costly doing it from the outside... doing it with INSTRUCTION with that logic would probably be even more costly). |
My original thinking was that this would be too slow. So here's a plan (for LINE events, nothing else changes)
This should also fix #103471 |
I'm experimenting with the new monitoring interface in PEP 669. The LINE event happens multiple times for the line in the body of a for loop (as I expect), but the for statement itself only gets an event on entering, not each time around the loop.
This code:
produces:
I would expect Line 4 to be monitored after each "LINE: 5", including after the last one.
This is with commit 263abd3 of CPython.
The text was updated successfully, but these errors were encountered: