Last Updated: Wednesday 14th August 2013

In one of the previous articles (Measure Time in Python - time.time() vs time.clock()), we learned how to use the module timeit to benchmark a program. Since the program we timed in that article includes only raw statements instead of functions, we're going to explore how to actually time a function in Python.

Time a Python Function Without Arguments

The module function timeit.timeit(stmt, setup, timer, number) accepts four arguments:

  • stmt which is the statement you want to measure; it defaults to 'pass'.
  • setup which is the code that you run before running the stmt; it defaults to 'pass'.
  • timer which a timeit.Timer object; it usually has a sensible default value so you don't have to worry about it.
  • number which is the number of executions you'd like to run the stmt.

Where the timeit.timeit() function returns the number of seconds it took to execute the code.

Now suppose you want to measure a function costly_func implemented like this:

You can measure its execution time using timeit:

Notice that we used two ways to measure this function. The first way passed in the Python callable costly_func while the second way passed in the raw Python statements of costly_func. Although the first way's timing overhead is a little larger than the second way, we usually prefer the first one since it's more readable and easier to maintain.

Time a Python Function with Arguments

We can use decorators to measure functions with arguments. Suppose our costly_func is defined in the following way:

You could measure it using a decorator defined like this:

Now you use this decorator to wrap costly_func with arguments into a function without arguments in order to pass it into timeit.timeit.

Time a Python Function From Another Module

Suppose you have the function costly_func defined in another module mymodule, how could you measure its time since it's not locally accessible? Well, you could import it into the local namespace or use the setup argument.

Summary and Tips

In this article, we learned how to measure a Python function's execution time using timeit.timeit. Usually, we prefer importing and passing the Python function as a callable object into timeit.timeit since it's more maintainable. In addition, remember that the default number of executions is 1000000 which could increase the total execution time a lot for certain complex functions.

To Practice: Try this interactive course on the basics of Lists, Functions, Packages and NumPy in Python.

About The Author

  • Hi, thanks this is very interesting.

    What is the main advantage of using the `timeit.timeit` method, compared with measuring the execution time of piece of code manually by taking the difference of the times after and before the executing the code? Also, with regards to the wrapper function, this seems to be a meta function, I am guessing *args refers to the arguments of the named function, in this case, costly_func, but I don’t know what **kwargs is referring to?

    • Hi Sandeep. Technically, there’s no difference; it’s just easier. a = timeit('foo()') is shorter than a = time() ; foo(); b = time() - a. Plus timeit() can run code prior (eg. print debug message) and the statement multiple times without using a for loop. **kwargs is an abbreviation of keyword arguments, checkout this SO post for more info.

  • toddle

    I can’t figure out what I done wrong. I want to compare 3 functions, using an array, my code so far:
    I have wrapper in an own file, what I import only one differnce:
    def wrapper(func, *args, **kwargs):
    def wrapped():
    return func(*args, **kwargs) #with colon here it didn’t worked
    return wrapped
    #a is a known array
    wrapped3 = wrapper(function_3, a)
    wrapped2 = wrapper(function_2, a)
    wrapped1 = wrapper(function_1, a)
    f3=timeit.timeit(wrapped3, number=100)
    f2=timeit.timeit(wrapped2, number=100)
    f1=timeit.timeit(wrapped1, number=100)
    print(“Function 3: “+str(f3))
    print(“Function 2: “+str(f2))
    print(“Function 1: “+str(f1))

  • Radu Popa

    Thank you very much. Very helpful !!!