Jpaji Rajnish
Jpaji Rajnish

Reputation: 1501

sys.settrace only getting called at function calls, not every line

I set a hook in sys.settrace which checks that the currently executing code object is one of my source files (is in the C: drive) and if it is, gives the line number to linecache to retrieve the line and then append it to a log file. But when I run this the hook only seems to get called on a function call and not every line like the docs indicate. This is not what I expect because in the tutorial I'm following: http://www.dalkescientific.com/writings/diary/archive/2005/04/20/tracing_python_code.html my code is very similar but in the example it's clear the sys.settrace hook gets called every line.

My tracing code:

from __future__ import with_statement
import sys
import re
import linecache


def startTracing():
    sys.settrace(lineHook)

def lineHook(frame, event, arg):
    scriptPath = "C:\MidiScript"
    lineno = frame.f_lineno

    p = re.compile(r"C:\\")
    filename = str(frame.f_code.co_filename)
    if p.match(filename):
        line = linecache.getline(filename, lineno)
        with open("C:\Midi Script\\test.txt", "a") as myfile:
            myfile.write("event: " + str(event) + "\targ: " + str(arg) + "\t" + "line " + str(frame.f_lineno) + ":\tline: " + line + "\n")
    return

Some of the output (lots of repetitions of this):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 115:   line:     def handle_sysex(self, midi_bytes):

event: call arg: None   line 111:   line:     def refresh_state(self):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

event: call arg: None   line 134:   line:     def _send_midi(self, midi_bytes, optimized = None):

Upvotes: 2

Views: 2018

Answers (2)

SemanticBeeng
SemanticBeeng

Reputation: 977

An example with "local trace function"s from https://pymotw.com/2/sys/tracing.html

Note how trace_calls returns trace_lines.

import sys

def trace_lines(frame, event, arg):
    if event != 'line':
        return
    co = frame.f_code
    func_name = co.co_name
    line_no = frame.f_lineno
    filename = co.co_filename
    print '  %s line %s' % (func_name, line_no)

def trace_calls(frame, event, arg):
    if event != 'call':
        return
    co = frame.f_code
    func_name = co.co_name
    if func_name == 'write':
        # Ignore write() calls from print statements
        return
    line_no = frame.f_lineno
    filename = co.co_filename
    print 'Call to %s on line %s of %s' % (func_name, line_no, filename)
    if func_name in TRACE_INTO:
        # Trace into this function
        return trace_lines
    return

def c(input):
    print 'input =', input
    print 'Leaving c()'

def b(arg):
    val = arg * 5
    c(val)
    print 'Leaving b()'

def a():
    b(2)
    print 'Leaving a()'

TRACE_INTO = ['b']

sys.settrace(trace_calls)
a()

Upvotes: 2

BrenBarn
BrenBarn

Reputation: 251373

Read the documentation again, specifically the part that says:

The trace function is invoked (with event set to 'call') whenever a new local scope is entered; it should return a reference to a local trace function to be used that scope, or None if the scope shouldn’t be traced.

Your trace function always returns None, so it doesn't trace in any scope.

Read the documentation again to understand how to use settrace.

Upvotes: 6

Related Questions