timeit.timeit variable importing in python
Asked Answered
N

4

9

I am trying to use timeit.timeit() in order to find how much time it takes to execute a specific line of code. The problem is that this line includes variables and I need to import them somehow, so my question is how? In order to be more clear, the code looks something like this:

def func():
    var1 = 'aaa'
    var2 = 'aab'
    t1 = timeit.timeit('var1==var2', 'from __main__ import ___', number = 10**4) #  here I'm missing what to put after the import

If I were trying to execute this code in __main__ I would just import the variable directly with 'from __main__ import var1, var2' Any solution for this kind of issue?

Nativity answered 21/7, 2015 at 22:36 Comment(0)
G
10

timeit.Timer takes a callable as well as a string to eval

Changed in version 2.6: The stmt and setup parameters can now also take objects that are callable without arguments. This will embed calls to them in a timer function that will then be executed by timeit(). Note that the timing overhead is a little larger in this case because of the extra function calls.

(also see the source, look for elif hasattr(stmt, '__call__'):).

Create a closure over the variables and pass it to timeit:

def func():
    var1 = 'aaa'
    var2 = 'aab'
    t1 = timeit.timeit(lambda: var1 == var2, number = 10**4)

or equivalently:

def func():
    var1 = 'aaa'
    var2 = 'aab'
    def closure():
        return var1 == var2
    t1 = timeit.timeit(closure, number = 10**4)
Gallop answered 22/7, 2015 at 21:50 Comment(0)
R
1

The accepted answer didn't work for me inside pdb debugger and a class method. The solution that worked is to add the variables to globals():

globals()['var1'] = var1
globals()['var2'] = var2
timeit.timeit(lambda: var1 == var2, number = 10**4)
Rupe answered 9/2, 2017 at 2:17 Comment(1)
I really like this solution.Sallie
S
0

The accepted answer's solution of using lambda creates large overhead. Comparison with an alternative, using a setup string:

func1 117.3 ms
func2  39.0 ms
func1 116.8 ms
func2  41.6 ms
func1 117.2 ms
func2  35.8 ms

If you're trying to measure such a very fast code snippet, or compare the times of multiple, you'd better not overshadow their execution times with such a function call's large overhead and its variance.

Benchmark code that produced the above results (Try it online!):

import timeit

def func1():
    s1 = 'aaa'
    s2 = 'aab'
    return timeit.timeit(lambda: s1 == s2)

def func2():
    setup = '''
s1 = 'aaa'
s2 = 'aab'
'''
    return timeit.timeit('s1 == s2', setup)

for func in [func1, func2] * 3:
    print(func.__name__,
          '%5.1f ms' % (func() * 1e3))
Solberg answered 19/5, 2022 at 21:17 Comment(0)
T
0

The globals argument takes a dictionary of variable names and values (i.e. a namespace). Simply pass global and local variables to the globals argument:

def func():
    var1 = 'aaa'
    var2 = 'aab'
    t1 = timeit.timeit('var1 == var2', number=10**4, 
                       globals={**globals(), **locals()})

This will make available all the variables: global and local (including defined functions). In case there are some name collisions, then local variables will take over.

Tumbling answered 10/5, 2023 at 14:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.