You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
frame.f_lineno doesn't get updated after local trace function assigned to it #51487
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2022-01-18.09:38:25.051>created_at=<Date2009-10-29.17:16:57.647>labels= ['interpreter-core', 'type-bug']
title="frame.f_lineno doesn't get updated after local trace function assigned to it"updated_at=<Date2022-01-18.09:38:25.050>user='https://bugs.python.org/eggy'
As you can see, when a local trace function sets f_lineno, f_lineno
doesn't get updated on subsequent lines. Otherwise it works fine.
$ python tracer_testcase.py
12
12
12
13
14
15
The reference manual (for python 2.6) states the following: "f_lineno is
the current line number of the frame — writing to this from within a
trace function jumps to the given line (only for the bottom-most frame).
A debugger can implement a Jump command (aka Set Next Statement) by
writing to f_lineno.". This is contradictory with the shown results,
because apparently it doesn't always represent the current line number.
1, You set trace function using sys.settrace(tracer).
2, When the following func() is called, tracer is called with a "call" event, so the trace function in PyThreadState is set to NULL since "sys.settrace(None)" is execute, but since the return value is a valid local trace function, the frame of called function("func()") has its local trace function.
3, The called function("func()") executes, though its frame has a local trace function, but it will not be executed since PyThreadState->c_tracefunc is NULL. When you get f_lineno from frame, you get the not refreshed f_lineno value but not the dynamically computed lineno, as the f_lineno's getter function said:
if(f->f_trace)
return f->f_lineno;
else
return PyCode_Addr2Line(f->f_code, f->f_lasti);
Here because your frame's local trace function is not executed, the f_lineno is not refreshed.
4, When the second time func() calls, there is no global trace function. Each time you get the f_lineno, it uses PyCode_Addr2Line() to get the dynamically computed line number.
I think this situation is so rarely that the doc saying "f_lineno is
the current line number of the frame" is correct.
Activity
eggy commentedon Oct 29, 2009
As you can see, when a local trace function sets f_lineno, f_lineno
doesn't get updated on subsequent lines. Otherwise it works fine.
$ python tracer_testcase.py
12
12
12
13
14
15
The reference manual (for python 2.6) states the following: "f_lineno is
the current line number of the frame — writing to this from within a
trace function jumps to the given line (only for the bottom-most frame).
A debugger can implement a Jump command (aka Set Next Statement) by
writing to f_lineno.". This is contradictory with the shown results,
because apparently it doesn't always represent the current line number.
ysjray commentedon Nov 24, 2010
It's not a bug. What happens is like this:
1, You set trace function using sys.settrace(tracer).
2, When the following func() is called, tracer is called with a "call" event, so the trace function in PyThreadState is set to NULL since "sys.settrace(None)" is execute, but since the return value is a valid local trace function, the frame of called function("func()") has its local trace function.
3, The called function("func()") executes, though its frame has a local trace function, but it will not be executed since PyThreadState->c_tracefunc is NULL. When you get f_lineno from frame, you get the not refreshed f_lineno value but not the dynamically computed lineno, as the f_lineno's getter function said:
if(f->f_trace)
return f->f_lineno;
else
return PyCode_Addr2Line(f->f_code, f->f_lasti);
Here because your frame's local trace function is not executed, the f_lineno is not refreshed.
4, When the second time func() calls, there is no global trace function. Each time you get the f_lineno, it uses PyCode_Addr2Line() to get the dynamically computed line number.
I think this situation is so rarely that the doc saying "f_lineno is
the current line number of the frame" is correct.
xdegaye commentedon Nov 19, 2012
See also the related bpo-16482.
iritkatriel commentedon Jan 10, 2022
I am unable to reproduce this on 3.11, I get this:
iritkatriel@Irits-MBP cpython % ./python.exe tracer_testcase.py
14
15
16
14
15
16
I am also unable to reproduce the problem in the related bpo-16482.