sys.settrace 'call' event behavior

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Michal Kwiatkowski

    sys.settrace 'call' event behavior

    I'm building a tool to trace all function calls using sys.settrace
    function from the standard library. One of the awkward behaviors of
    this facility is that the class definitions are reported as 'call'
    events.[1] Since I don't want to catch class definitions, only
    function calls, I'm looking for a way to differentiate between those
    two. So far I have only vague clues about how to do that.

    At the bottom of this mail is a simple script that prints all
    attributes (except for the bytecode) of the traced code. In the sample
    code Bar class is defined and foo function is called after that. The
    following trace output is reported:

    Bar, 0, 0, (), (), (), (None,), ('__name__', '__module__', 'None'),
    foo.py, 21, , 1, 66
    foo, 0, 0, (), (), (), (None,), (), foo.py, 25, , 1, 67

    Class definition and function call differs on four attributes. Two of
    them, co_name and co_firstlineno are not very helpful. Other two are
    co_names and co_flags. The latter differs only by the CO_OPTIMIZED
    flag, which is for "internal use only"[2]. So we're left with
    co_names, which "is a tuple containing the names used by the
    bytecode". Is that helpful in distinguishing between class definitions
    and function calls? Do you have any other ideas on how to tell them
    apart?

    Source of the sample script I used follows.

    def trace(frame, event, arg):
    if event == 'call':
    print ', '.join(map(str, [frame.f_code.co _name,
    frame.f_code.co _argcount,
    frame.f_code.co _nlocals,
    frame.f_code.co _varnames,
    frame.f_code.co _cellvars,
    frame.f_code.co _freevars,
    frame.f_code.co _consts,
    frame.f_code.co _names,
    frame.f_code.co _filename,
    frame.f_code.co _firstlineno,
    frame.f_code.co _lnotab,
    frame.f_code.co _stacksize,
    frame.f_code.co _flags]))
    return trace

    import sys
    sys.settrace(tr ace)

    class Bar(object):
    None
    pass

    def foo():
    pass

    foo()

    [1] It is strange for me, but documented properly.
    http://docs.python.org/lib/debugger-hooks.html says that call event
    happens when "a function is called (or some other code block
    entered)."

    [2] http://docs.python.org/ref/types.html#l2h-145

    Cheers,
    mk
Working...