Profiling/tracing a single function - Random notes from mg (original) (raw)

Sometimes you want to profile just a single function in your Python program. Here's a module that lets you do just that: profilehooks.py. Sample usage:

#!/usr/bin/python from profilehooks import profile

class SampleClass:

def silly_fibonacci_example(self, n):
    """Return the n-th Fibonacci number.

    This is a method rather rather than a function just to illustrate that
    you can use the 'profile' decorator on methods as well as global
    functions.

    Needless to say, this is a contrived example.
    """
    if n < 1:
        raise ValueError('n must be >= 1, got %s' % n)
    if n in (1, 2):
        return 1
    else:
        return (self.silly_fibonacci_example(n - 1) +
                self.silly_fibonacci_example(n - 2))
silly_fibonacci_example = profile(silly_fibonacci_example)

if name == 'main': fib = SampleClass().silly_fibonacci_example print fib(10)

(If you have Python 2.4, you can use @profile as a decorator just before the function definition instead of rebinding silly_fibonacci_example.)

Demonstration:

mg: ~$ python sample.py 55

*** PROFILER RESULTS *** silly_fibonacci_example (sample.py:6) function called 109 times

     325 function calls (5 primitive calls) in 0.004 CPU seconds

Ordered by: internal time, call count

ncalls tottime percall cumtime percall filename:lineno(function) 108/2 0.001 0.000 0.004 0.002 profilehooks.py:79() 108/2 0.001 0.000 0.004 0.002 profilehooks.py:131(call) 109/1 0.001 0.000 0.004 0.004 sample.py:6(silly_fibonacci_example) 0 0.000 0.000 profile:0(profiler)

This decorator is useful when you do not want the profiler output to include time spent waiting for user input in interactive programs, or time spent waiting for requests in a network server.

In a similair vein you can produce code coverage reports for a function.

#!/usr/bin/python import doctest from profilehooks import coverage

def silly_factorial_example(n): """Return the factorial of n.""" if n < 1: raise ValueError('n must be >= 1, got %s' % n) if n == 1: return 1 else: return silly_factorial_example(n - 1) * n silly_factorial_example = coverage(silly_factorial_example)

if name == 'main': print silly_factorial_example(1)

Demonstration:

mg: ~$ python sample2.py 1

*** COVERAGE RESULTS *** silly_factorial_example (sample2.py:5) function called 1 times

   def silly_factorial_example(n):
       """Return the factorial of n."""
1:     if n < 1:
    raise ValueError('n must be >= 1, got %s' % n)
1:     if n == 1:
1:         return 1
       else:
    return silly_factorial_example(n - 1) * n

2 lines were not executed.

I found it useful to discover whether a given function or a method was adequately covered by unit tests.

Update: profilehooks is now a proper easy_install'able Python package.