sys.settrace 'call' event behavior

R. Bernstein rocky at panix.com
Thu Dec 11 05:06:31 EST 2008


On Jun 21, 8:47 am, Michal Kwiatkowski <constant.b... at gmail.com> wrote:
> I'm building a tool to trace all function calls usingsys.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 functioncalldiffers 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):
>     ifevent== '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 syssys.settrace(trace)
> 
> 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.htmlsays thatcallevent
> happens when "a function is called (or some other code block
> entered)."
> 
> [2]http://docs.python.org/ref/types.html#l2h-145
> 
> Cheers,
> mk

Perhaps you could filter based on the type of the frame.f_code.co_name ? 
e.g. or type(eval(frame.f_code.co_name))

(Sorry for the delayed reply - I don't generally read the newsgroup
and stumbled across this looking for something else. But I noticed no
replies, so...)



More information about the Python-list mailing list