Missing 'line' event when writing to frame.f_lineno in trace function


C

CTS

Hello all,

I've been playing with sys.settrace() in an attempt to better
understand how trace functions (and debugging) work. I'm running
Python3.2 on Windows, which I installed by running the installer
package (i.e. I did not compile from source code).

Here's my code, some of which I borrowed from Pdb/Bdb. The trace
function basically prints out the event type, the filename, and the
line number, and asks the user what to do next. If "jump <line>" is
entered, <line> is written to frame.f_lineno before moving on.
Otherwise, we just move on to the next trace event.

# ---------- BEGIN tracing code -------------------
import sys
import __main__
import re

class Tracer:

def __init__( self, filename ):
__main__.__dict__.clear()
__main__.__dict__.update( {
"__name__": "__main__",
"__file__": filename,
"__builtins__": __builtins__, } )

with open( filename, "rb" ) as file:
code = compile( file.read(), filename, 'exec')

sys.settrace( self.trace )

exec( code, __main__.__dict__ )

def trace( self, frame, event, arg ):

filename = frame.f_code.co_filename
line = frame.f_lineno

prompt = event + " -> " + filename + "(" + str( line ) + "):"
action = input( prompt )

tokens = re.split( " +", action )

if tokens[ 0 ] == "jump":
frame.f_lineno = int( tokens[ 1 ] )

return self.trace

def run( filename ):
Tracer( filename )
# ---------- END end tracing code -------------

I start tracing a script's execution by typing the following at the
interactive prompt:

Given the following code,

# ----- BEGIN traced script ------
print( "Line 1" )
print( "Line 2" )
print( "Line 3" )
print( "Line 4" )
# ----- END traced script-------

.... I get the following output if I just step though from beginning to
end:

# BEGIN output (no writes to frame.f_lineno)
C:\python_tests>python
Python 3.2 (r32:88445, Feb 20 2011, 21:29:02) [MSC v.1
32
Type "help", "copyright", "credits" or "license" for mcall -> just_prints.py(1):
line -> just_prints.py(1):
call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 1call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

line -> just_prints.py(2):
call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 2call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

line -> just_prints.py(3):
call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 3call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

line -> just_prints.py(4):
call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 4call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

return -> just_prints.py(6):# END output (no writes to frame.f_lineno)

So, as expected, I get "line" events for each of my script's lines,
and it appears that the print() built-in calls some helper functions
in lib\encodings\cp437.py, which is fine and explainable.

Now, if I try to jump to any line during the trace (in the following
output, after I'm done with line 3, I try to jump back to line 1 by
writing "1" to frame.f_lineno), I don't get the "line" event; instead
I go directly to the first "call" event of file cp437.py:

# BEGIN output (with a write to frame.f_lineno)
C:\python_tests>python
Python 3.2 (r32:88445, Feb 20 2011, 21:29:02) [MSC v.1500 32 bit (
32
Type "help", "copyright", "credits" or "license" for more informatcall -> just_prints.py(1):
line -> just_prints.py(1):
call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 1call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

line -> just_prints.py(2):
call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 2call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

line -> just_prints.py(3):
call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 3call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

line -> just_prints.py(4):jump 1 <=======
write to frame.f_lineno
call -> c:\python32\lib\encodings\cp437.py(18): <======= No "line"
event !!!!
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):
Line 1call -> c:\python32\lib\encodings\cp437.py(18):
line -> c:\python32\lib\encodings\cp437.py(19):
return -> c:\python32\lib\encodings\cp437.py(19):

line -> just_prints.py(2):
# <snip>
# END output (with a write to frame.f_lineno)

The above behavior occurs both when I jump back, as well as forward in
a script. My questions to the group:

1) I was expecting a "line" event for line 1 of my traced script right
after I wrote "1" to frame.f_lineno, shouldn't that event have been
passed to my trace function?
2) Is there a way to get the missing "line" event by any means other
than by writing to frame.f_lineno?

My apologies for the lengthy message.

Thanks in advance for your insights,

-CTS
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top