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: >>> import tracer >>> tracer.run( "insert file name here" ) 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 m >>> import tracer >>> tracer.run('just_prints.py') call -> 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 informat >>> import tracer >>> tracer.run( 'just_prints.py') call -> 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 -- http://mail.python.org/mailman/listinfo/python-list