Three four ways of measuring time in Python:

  • start = time.time()
  • timer()
  • datetime.now()
  • advanced profiling with cProfile

My personal favorite for simple time measurement of method is time. While for complex performance measurement I like to use cProfile which is giving comprehensive information on the price for several lines of code.

Measure time by module time

First way is by using module time. In this example we are calculating the 42-th Fibonacci number. We measure the time and print it out in ms, seconds and minutes

import time

def fib(i):
    if i <= 2:
        return 1;
    else:
        f = fib(i-1) + fib(i-2)
    return f

start = time.time()

print(fib(42))

end = time.time()
execution_time = end - start

print ('--- %0.3fms. --- ' % ( execution_time*1000.))
print("--- %s seconds ---" % (execution_time ))
print("--- %s minutes ---" % (execution_time / 60))

result:

267914296
--- 92015.864ms. --- 
--- 92.01586437225342 seconds ---
--- 1.533597739537557 minutes ---

Measure time by datetime

The same execution of Fibonacci measured by datetime module and returning the time in hh:mm:ss.ms

from datetime import datetime

def fib(i):
    if i <= 2:
        return 1;
    else:
        f = fib(i-1) + fib(i-2)
    return f

start_time = datetime.now()

print(fib(42))

time_elapsed = datetime.now() - start_time
print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

result:

267914296
Time elapsed (hh:mm:ss.ms) 0:01:32.943911

Measure time by datetime

Last example uses timeit and default_timer to test record the elapsed time.

from timeit import default_timer as timer

def fib(i):
    if i <= 2:
        return 1;
    else:
        f = fib(i-1) + fib(i-2)
    return f

start = timer()

print(fib(42))

end = timer()
print("--- %s seconds ---", (end - start)/1.)

result:

267914296
--- %s seconds --- 93.60394597499999

Advanced profiling with cProfile

If you need to do more complex and better time measurement then you can use the module which offer Profiling - cProfile. It's mature and offers good results with few lines of code. Below we are measuring 3 methods:

  • fib
  • foo
  • bar

As you can see from the result you have total time and separate time for each of this methods. Another advantage of the method is the information returned like:

  • total calls of the method
  • time spent total and per method
  • line number of the method

You can see the example below testing Fibonacci with two additional functions:

import cProfile


def foo():
    s = 0
    for x in range(0, 1000):
        s +=x

def bar():
    s = 0
    for x in range(0, 3000):
        s +=x

def fib(i):
    foo()
    bar()
    if i <= 2:
        return 1;
    else:
        f = fib(i-1) + fib(i-2)
    return f

cProfile.run('fib(20)')

result:

         40590 function calls (27062 primitive calls) in 2.373 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.373    2.373 <string>:1(<module>)
  13529/1    0.008    0.000    2.373    2.373 Profiling.py:14(fib)
    13529    0.578    0.000    0.578    0.000 Profiling.py:4(foo)
    13529    1.787    0.000    1.787    0.000 Profiling.py:9(bar)
        1    0.000    0.000    2.373    2.373 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

What to use

As you can see the results for this 3 options are very close. The result depends on OS, running code, parallel execution. In order to get optimal results you need to do some test for your requirements. All these tests were done on Linux.