-
-
Notifications
You must be signed in to change notification settings - Fork 31.8k
Setting f_trace_opcodes
to True
can lead to f_lineno
being removed in some cases (using breakpoint()
/pdb.set_trace()
)
#127321
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
I'm not able to reproduce this on either [1, 2] and breakpoint()
|
Ok took some time to find how to reproduce, but turns out you need at least one extra statement after the breakpoint call. So something like: [1,2] and breakpoint()
a = 1 should work. |
Ah, interesting. Worked for me, thanks! |
@iritkatriel the bytecode of [1, 2] and breakpoint()
a = 2 is
The label |
The There are situations (such as |
Because The workaround could be stop at opcode that has line number, but in this case, the next instruction belongs to the next line, which would break the behavior that |
Can the breakpoint builtin do something to help know where it is? |
Well it also affects
As this is a rare case, I don't think either of the options above is horrible (although I'm a bit hesitated about 2. as it impacts too much code in pdb). However, from the other point of view, none of the options is perfect either. My perfect solution was for the opcode to have a line number, but maybe that's too much a burden for the compiler. |
It's not that it's a burden on the compiler. It's that line numbers are static, so if you can reach this NOP from two different paths, you need to make two copies of this NOP, and then add a jump over one of the copies to the next instruction (here it's the |
It might be possible to improve the situation if the compiler does propagate the line number if it's the same for both predecessors (as it is in this example). It won't completely fix the problem, this will still not work:
|
Yeah I understand the problem behind. I actually have a question here: If the compiler knows the return value is not used, why does it need to copy the return value? Can it do a simple Also, even if we want a single I think line numbers are majorly used by debuggers, so it's debugging information anyway (correct me if I'm wrong). "I don't know where this opcode is generated" is correct by less useful information for debugging. |
It's a feature of the language that the result of a boolean expression is the value of the element that gave the truthy result:
It's common to use this for None handling:
The last line of the expression may not have executed. we want the POP_TOP to have the line number of the last instruction from the expression that executed, otherwise it would mess up the trace.
They are also used for other things, like tracebacks and coverage. Coverage is particularly sensitive to inaccurate line numbers. |
These are cases where the expressions are assigned to a variable, and this is not causing issue if I understood correctly. I meant for the cases where the expressions are not assigned to anything, so the value is unused. We should be able to optimize that case right? It's faster and it generates less code (and it's rare).
Hmm okay it might even generate a new line event which is probably something we don't want. I guess I'll have to deal with this in pdb. |
…ber for breakpoint() (#127457)
…ated line number for breakpoint() (pythonGH-127457) (cherry picked from commit 1bc4f07) Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
This is fixed in main and backported to 3.13. |
…ne number for breakpoint() (python#127457)
…ne number for breakpoint() (python#127457)
…ne number for breakpoint() (python#127457)
Bug report
Bug description:
Since #118579 (introduced in 3.13),
Bdb.set_trace
will callBdb.set_stepinstr
instead ofBdb.set_step
(on L406):cpython/Lib/bdb.py
Lines 389 to 407 in 6d3b520
This ends up setting
f_trace_opcodes
to True on all the frames of the stack.This is fine for most use cases, but for some reason, this removes the
f_lineno
attribute of frames in exotic setups usingbreakpoint()
:I'm using these inline conditions a lot to conditionally add a breakpoint, and not having access to the line number is annoying as many commands (such as
list
) will fail because they expectframe.f_lineno
to not beNone
(and thus crashes and exits the debugger).I'm not familiar with opcodes and how this interacts with frames. It is expected for the
f_lineno
to be lost here?CPython versions tested on:
3.13, 3.14
Operating systems tested on:
Linux
Linked PRs
The text was updated successfully, but these errors were encountered: