[Tutor] trace / profile function calls with inputs
spir
denis.spir at gmail.com
Mon Feb 10 13:09:37 CET 2014
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
More information about the Tutor
mailing list