Python Timeit Module (With Examples)

Learn how to use the python timeit module to measure the execution time of your Python code.

Python Timeit Module (With Examples)
timeit library in Python

Sections Covered

  1. Python timeit vs time module
  2. Using timeit in your Python script
  3. Using timeit with Python functions
  4. Using timeit on command line

Python timeit vs time module

Let’s assume you want to return all the characters in a string as a python list.

You can follow 2 different approaches.

Approach 1 - Use a for loop

name = "Pylenin" 
result_list = [] 
for char in name: 
    result_list.append(char) 
    
#Result 
>>> ['P', 'y', 'l', 'e', 'n', 'i', 'n']

Approach 2 - Use a list comprehension

name = "Pylenin" 
result_list = [char for char in name] 

#Result 
>>> ['P', 'y', 'l', 'e', 'n', 'i', 'n']

Both these approaches give you the same result. But which one is fastest?

The timeit module in python helps you measure execution time of your Python code.

Advantages of timeit over time module?

  1. It ignores the background processes running on your system, which might have an impact on your code execution.
  2. By default, timeit performs 1 million executions before providing you with an estimate. This allows you to have statistically relevant measurements.

Using timeit in your Python script

Let’s use the timeit module to get some insights.

  1. Step 1 - Import the timeit module

    import timeit
    
  2. Step 2 - Write the setup code

    The setup code is the part of code that is essential for you to run the main code that does all the computing.

    Think of all the libraries you are importing and the variables you are declaring. These multiple lines of code qualify as a setup code.

     #Step 2 
     setup_code = """
     name = "Pylenin"
     result_list = []
     """
    
  3. Step 3 - Write your main code

    The main code is basically the snippet of code, whose execution time you want to measure.

    In this case, we want to compare the execution times of a for loop vs list comprehension. Those snippets will go in the main code.

    #Step 3
    main_code = """
    for char in name:
        result_list.append(char)
    """
    
  4. Step 4 - Call the timeit function

    With both the main_code and setup_code statements defined, you can pass those as parameters into the timeit function.

    The stmt parameter takes in the main_code statement. The setup parameter takes in the setup_code statement. The number parameter takes in the number of executions(by default it is 1 million). You can pass in multiple lines of code as part of your main_code and setup_code in your timeit function.

    #Step 4
    print(timeit.timeit(stmt=main_code,
              setup=setup_code,
              number=10000))
    

    The execution time of the setup code is excluded from the results.


Overall, this is what your code will look like.

# Python timeit Example
import timeit

setup_code = """
name = "Pylenin"
result_list = []
"""

main_code = """
for char in name:
    result_list.append(char)
"""

print(timeit.timeit(stmt=main_code,
                    setup=setup_code,
                    number=10000))

#Result
>>> 0.00629170099273324

The output of the above program is the execution time(in seconds) for 10000 executions. To get the time per execution, divide the result with the number of executions.

Let's compare the execution time of a for loop with list comprehension.

import timeit

setup_code_1 ="""
name = "Pylenin"
result_list = []
"""

main_code_1 ="""
for char in name:
    result_list.append(char)
"""

t1 = timeit.timeit(stmt=main_code_1,
                    setup=setup_code_1,
                    number=10000)

setup_code_2 ="""
name = "Pylenin"
"""

main_code_2 ="""
result_list = [char for char in name] 
"""

t2 = timeit.timeit(stmt=main_code_2,
                    setup=setup_code_2,
                    number=10000)

print(f"10000 runs of For Loop is {t1}")
>>> 10000 runs of For Loop is 0.005563209997490048

print(f"10000 runs of List Comprehension is {t2}")
>>> 10000 runs of List Comprehension is 0.0036344139953143895

It is obvious from the result that a list comprehension is much more efficient than using a simple for loop.

You use the timeit module to benchmark different methods in Python and figure out the fastest way.

You could also repeat your calls to the timeit function.

Let’s say you are unsure of the results provided by timeit. You can pass in an additional parameter called repeat to the timeit.repeat function.

The timeit.repeat is similar to the timeit.timeit method, except, it accepts an additonal parameter repeat which tells the number of times the benchmarking has to be performed.

import timeit

setup_code = """
name = "Pylenin"
result_list = []
"""

main_code = """
for char in name:
    result_list.append(char)
"""

print(timeit.repeat(stmt=main_code,
                    setup=setup_code,
                    number=10000,
                    repeat=3))

#Result
>>> [0.005725524999434128, 0.00546123698586598, 0.005446395982289687]

This returns you all the execution times of calling the timeit function. But which of the 3 results is correct?

The Python 3 documentation suggests that the minimum of the result list is what you should take into account. The higher values could be noise interfering with your timing accuracy.


Using timeit with Python functions(with arguments)

You can also use the timeit module with functions.

Let us perform the above bench marking experiment in a different way. We will write functions for each of the approach.

import timeit

def for_loop(seq, result_list=[]):
    for char in seq:
        result_list.append(char)
    return result_list

def list_comprehension(seq):
    return [char for char in seq]

print(timeit.timeit(stmt = "for_loop(seq)",
                    setup="seq='Pylenin'",
                    number=10000))

print(timeit.timeit(stmt = "list_comprehension(seq)",
                    setup="seq='Pylenin'",
                    number=10000))

When you run the above code, it will throw you a NameError.

Traceback (most recent call last):
.....
NameError: name 'for_loop' is not defined

Now, Why is that?

This is because with timeit module, your code runs in a different namespace. So it doesn’t recognize the functions you have defined in your global namespace. In order for timeit to recognize your functions, you need to import it to the same namespace. You can achieve this by passing from __main__ import func_name to the setup argument.

import timeit

def for_loop(seq, result_list=[]):
    for char in seq:
        result_list.append(char)
    return result_list

def list_comprehension(seq):
    return [char for char in seq]

setup_code_1="""
from __main__ import for_loop
seq = 'Pylenin'
"""

setup_code_2="""
from __main__ import list_comprehension
seq = 'Pylenin'
"""

print(timeit.timeit(stmt = "for_loop(seq)",
                    setup=setup_code_1,
                    number=10000))
>>> 0.006762586999684572

print(timeit.timeit(stmt = "list_comprehension(seq)",
                    setup=setup_code_2,
                    number=10000))
>>> 0.004485986020881683

Now your code is going to work properly and return the execution time(in seconds) for 10000 runs of each function.

The above way however, might seem exhaustive. If you don’t want that, you could pass the globals() built-in function into the globals parameter in the timeit class.

import timeit

def for_loop(seq, result_list=[]):
    for char in seq:
        result_list.append(char)
    return result_list

def list_comprehension(seq):
    return [char for char in seq]


print(timeit.timeit(stmt = "for_loop(seq)",
                    setup="seq='Pylenin'",
                    number=10000,
                    globals=globals()))
>>> 0.006524929020088166

print(timeit.timeit(stmt = "list_comprehension(seq)",
                    setup="seq='Pylenin'",
                    number=10000,
                    globals=globals()))
>>> 0.004345747991465032

This way, you don’t have to write that giant import statement every time.


Using timeit on command line in Python

Now the above examples were suitable for measuring execution times of multiple lines of code with timeit. If you want to test out very small, single-line snippets of code, you could also do it from the command line.

python3 -m timeit '"-".join(char for char in "Pylenin")'
>>> 1000000 loops, best of 3: 0.851 usec per loop

Now the above example is based on the assumption that your system has both Python 2 and Python 3. If you only have one version of Python, you can use python in your command line.

You can also add multiple command line arguments to the above.

-r, –repeat

How many times to repeat?

-n, –number

How many times to execute the statement?

-s, –setup

The setup code for executing the main statement.

-u, –unit

Time unit for the timer output. It could be nsec, usec, msec, or sec.

Below is an example using the above arguments.

python3 -m timeit -n 1000 -r 3 -u sec -s "x = 'Pylenin'" '"-".join(char for char in "Pylenin")'
>>> 1000 loops, best of 3: 8.54e-07 sec per loop

So the above was an detailed overview on the timeit module in Python. If you have some better examples to share, share with me on Twitter.

Subscribe to Pylenin

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe