This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: frame.f_lineno doesn't get updated after local trace function assigned to it
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: out of date
Dependencies: Superseder:
Assigned To: Nosy List: eggy, iritkatriel, jcea, ncoghlan, xdegaye, ysj.ray
Priority: normal Keywords:

Created on 2009-10-29 17:16 by eggy, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
tracer_testcase.py eggy, 2009-10-29 17:16
Messages (4)
msg94681 - (view) Author: Mark Florisson (eggy) * Date: 2009-10-29 17:16
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.
msg122279 - (view) Author: ysj.ray (ysj.ray) Date: 2010-11-24 14:08
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.
msg175969 - (view) Author: Xavier de Gaye (xdegaye) * (Python triager) Date: 2012-11-19 21:05
See also the related issue 16482.
msg410265 - (view) Author: Irit Katriel (iritkatriel) * (Python committer) Date: 2022-01-10 23:31
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 issue 16482.
History
Date User Action Args
2022-04-11 14:56:54adminsetgithub: 51487
2022-01-18 09:38:25iritkatrielsetstatus: pending -> closed
resolution: out of date
stage: needs patch -> resolved
2022-01-10 23:31:23iritkatrielsetstatus: open -> pending
nosy: + iritkatriel
messages: + msg410265

2013-02-25 17:45:17jceasetnosy: + jcea
2012-11-19 21:05:45xdegayesetnosy: + xdegaye
messages: + msg175969
2011-11-29 06:20:35ezio.melottisetnosy: + ncoghlan

versions: + Python 3.3, - Python 3.1
2010-11-24 14:08:08ysj.raysetnosy: + ysj.ray
messages: + msg122279
2010-07-11 10:10:47BreamoreBoysetstage: needs patch
versions: - Python 2.6, Python 2.5, Python 2.4, Python 3.0
2009-10-29 17:16:57eggycreate