Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Timeit and “global name ... is not defined”

I have a problem with timit function for code optimization. For example, I writing functions with parameters in a file, let's call it myfunctions.py containing :

def func1(X):
    Y = X+1
    return Y

and I test this function in a second file test.py where I call the timer function to test code performance (in obviously more complex problems!) containing :

import myfunctions
X0 = 1
t = Timer("Y0 = myfunctions.func1(X0)")
print Y0
print t.timeit()

The Y0 is not calculated, and even if I comment print Y0 line the error global name 'myfunctions' is not defined occured.

If I specify the setup with the command

t = Timer("Y0 = myfunctions.func1(X0)","import myfunctions")

now the error global name 'X0' is not defined occurred.

Is someone know how to solve this ? Many thanks.

like image 303
cedm34 Avatar asked Jan 04 '12 12:01

cedm34


2 Answers

You need setup parameter. Try:

Timer("Y0 = myfunctions.func1(X0)", setup="import myfunctions; X0 = 1")
like image 185
Roman Bodnarchuk Avatar answered Oct 10 '22 10:10

Roman Bodnarchuk


The reason for Y0 being undefined is that you have defined that in a string, but at parse time in the beginning of the execution the string is not evaluated yet to bring the variable into life. So put an Y0 = 0 somewhere at the top of your script to have it defined beforehand.

All external functions and variables must be given to Timer using its setup argument. So you need "import myfunctions; X0 = 1" as the setup parameter.

This will work:

from timeit import Timer
import myfunctions
X0 = 1
Y0 = 0     #Have Y0 defined
t = Timer("Y0 = myfunctions.func1(X0)", "import myfunctions; X0 = %i" % (X0,))
print t.timeit()
print Y0

Look how I used "X0 = %i" % (X0,) to pass in the real value of the external X0 variable.

Another thing you might want to know is that if there are any functions in your main file that you want to use in timeit, you can make timeit recognize them by passing from __main__ import * as the second argument.


If you want timeit to be able to modify your variables, then you shouldn't pass strings to them. More conveniently you can pass callables to it. You should pass a callable that changes your desired variable. You don't need setup then. Look:

from timeit import Timer
import myfunctions

def measure_me():
    global Y0    #Make measure_me able to modify Y0
    Y0 = myfunctions.func1(X0)

X0 = 1
Y0 = 0     #Have Y0 defined
t = Timer(measure_me)
print t.timeit()
print Y0

As you see, I put print Y0 after print t.timeit() since before execution you can't have its value changed!

like image 4
Hossein Avatar answered Oct 10 '22 10:10

Hossein