Claira
Claira

Reputation: 31

How can I use the cProfile module to time each funtion in python?

I have a program in Python that takes in several command line arguments and uses them in several functions. How can I use cProfile (within my code)to obtain the running time of each function? (I still want the program to run normally when it's done). Yet I can't figure out how, for example I cannot use

cProfile.run('loadBMPImage(sys.argv[1])')

to test the run time of the function loadBMPImage. I cannot use sys.argv[1] as an argument. Any idea how I can use cProfile to test the running time of each function and print to stdout, if each function depends on command line arguments? Also the cProfile must be integrated into the code itself. Thanks

Upvotes: 3

Views: 4079

Answers (3)

alex
alex

Reputation: 955

my 2 pence.

when running python3 -m cProfile yourprogram.py, the cwd and sys.argv[0] seems to get changed (i didn't check thoroughly), thus hurting the implicit context of yourprogram, especially if it's being usually run as executable.

thus, i'd rather recommend wrapping your original code in a function, and run it by cProfile.run(), even though your code changes a little.

def yourfunction():
    import sys
    print (sys.argv)

import cProfile
cProfile.run("yourfunction()")

good luck!

Upvotes: 0

Harish Agrawal
Harish Agrawal

Reputation: 41

I run the

python program with -m cProfile

example:

python -m cProfile <myprogram.py>

This will require zero changes to the myprogram.py

Upvotes: 4

fjarri
fjarri

Reputation: 9726

There are several ways.

import cProfile
import pstats

import sys


def function(n):
    a = 1
    for i in range(n):
        a += 1
    return a

First one is to use a simple wrapper runctx() that allows you to specify globals and locals for the executed string. In the example below I use globals() to pass the function object, and locals to pass the parameter, but it can be arranged differently, of course.

def profile1():
    cProfile.runctx("function(n)", globals(), dict(n=int(sys.argv[1])), filename='test')
    return pstats.Stats('test')

A better way where you don't need to mess with exec is to use the Profile class. This way you can just profile a piece of regular code:

def profile2():
    pr = cProfile.Profile()
    pr.enable()
    function(int(sys.argv[1]))
    pr.disable()
    return pstats.Stats(pr)

Just for completeness' sake to make the example runnable

if __name__ == '__main__':
    profile1().print_stats()
    profile2().print_stats()

Upvotes: 4

Related Questions