On 02/08/2014 05:36 PM, Richard Cziva wrote:
Hi All,

I am trying to print out every function that is being called while my Python
program is running (own functions and library calls too). I can not modify the
Python programs I am trying to profile.

Let me give an example. A program contains a function like this:

def foo(x):
   y = math.cos(x)
   z = 1 + 1
   time.sleep(y+1)
   return x * 50

And it calls the function:

print foo(100)

I would like to retrieve an execution trace that shows me each function called
with the value or hash of its arguments. According to the example, I am looking
for a technique to extract something similar:

foo(100)
math.cos(100)
time.sleep(0.87)

Things I have tried with only partial success:
- trace module
- profile module / cProfile

Could you suggest me a way of doing this?

You need to wrap every function call in a tracing wrapper function that (1) does what you want (2) calls the wrapped function. Something like this:

def trace (func, *args):
    # trace
    func_name = func.__name__
    arg_strings = (str(arg) for arg in args)
    arg_string = ", ".join(arg_strings)
    print("%s(%s)" % (func_name, arg_string))
    # call
    result = func(*args)
    if result: return result

def f (x,y):
    return (x+y) / 2
def g (x,y):
    print((x+y) / 2)

trace(g, 3, 7)
z = trace(f, 3, 7)
print(z)

==>

g(3, 7)
5.0
f(3, 7)
5.0

As you see, there is a subtility about the distinction between functions that _do_ something (actions, in fact) and function that compute a product (function properly speaking). But actually you could ignore because the former implicitely return none.

You cannot always have the same call expression as in the actual calling code: you always have the _values_. For example:
        a = 9
        y = 7
        trace(f(math.sqrt(a), y)
will show:
        f(3, 7)
Python does not let you know _the code_. You would need a "homoiconic" language like Lisp for that: a language in which "code is data" (data of the language types). In python, code is opaque, it is plain raw data (bit string) without any language type & value. So, I guess we cannot do much better than the above, but I may be wrong.

The right way to do this would in fact be using so-called "decorators". But the example above shows the principle (and the code you'd have to put in a decorator).

d
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor

Reply via email to