trace function calls to get signatures

harold fellermann harold.fellermann at upf.edu
Sat Jul 2 10:41:18 EDT 2005


Hi all,

I am trying to write a script that prints out the signatures
of each function call that occurs during the execution of
a second script which is invoked by my program. i.e. if the
inspected program is 'foo.py':

	def bar(x,y,z=None) : pass
	bar(1,"a",bar)
	bar(2,int)

the output of my script should be:
	foo.bar(int,str,function)
	foo.bar(int,type,NoneType)


I thought I go for sys.settrace() and achieved the following:

import sys
import types

def tracefunc(frame,event,arg) :
     if event is 'call' : return trace_call(frame,event,arg)
     else : return None

def trace_call(frame,event,arg) :
     code = frame.f_code
     scope = frame.f_locals
     try :
         print code.co_name+"("+",".join(
                 [ str(type(scope[var])).split("'")[1]
                     for var in code.co_varnames
                 ]
             )+")"
     except KeyError : pass
     return None

if __name__ == "__main__" :
     prog = sys.argv[1]
     sys.argv.pop(0)
     sys.settrace(tracefunc)
     __import__(prog)


the output of the above example is:
	bar(int,str,function)
	bar(int,type,NoneType)

which is pretty close, but I need / would like to improve several 
things,
but have no idea how to do it:

1. I would like to have not only the name of the functions and type 
arguments
    but their full package/module/class-path, e.g.
    xml.dom.pulldom.PullDOM.clear
    However, I cannot find a way from the frame object to the function 
object
    where I could find the information.

2. The KeyError in my code is raised by the "from XXX import" statement:
    "from distutils import setup" results in

      File "tracetest.py", line 28, in ?
        __import__(prog)
      File "/Volumes/space/Users/harold/uni/pace/dpd/setup.py", line 1, 
in ?
        from distutils.core import setup, Extension
      File "tracetest.py", line 5, in tracefunc
        if event is 'call' : return trace_call(frame,event,arg)
      File "tracetest.py", line 12, in trace_call
        print code.co_name+"("+",".join(
      KeyError: 'setup'

    does anyone know how I can circumvent this?

3. Is there any way to set the __name__ attribute for the inspected 
script to
    "__main__", so that tracing is really transparent?

4. finally, does a functionality like this already exist in the library 
or
    did anyone of you come up with an implementation?

thanks,

- harold -


--
Military intelligence is a contradiction in terms.
-- Groucho Marx




More information about the Python-list mailing list