2009-02-15 22 views
73

Estoy tratando de averiguar cuánto tiempo lleva ejecutar una instrucción Python, así que busqué en línea y encontré que la biblioteca estándar proporciona un módulo llamado timeit que pretende hacer exactamente eso:Obtener "nombre global 'foo' no está definido" con timeit de Python

import timeit 

def foo(): 
    # ... contains code I want to time ... 

def dotime(): 
    t = timeit.Timer("foo()") 
    time = t.timeit(1) 
    print "took %fs\n" % (time,) 

dotime() 

sin embargo, esto produce un error:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in dotime 
    File "/usr/local/lib/python2.6/timeit.py", line 193, in timeit 
    timing = self.inner(it, self.timer) 
    File "<timeit-src>", line 6, in inner 
NameError: global name 'foo' is not defined 

todavía soy nuevo en Python y no entiendo plenamente todas las cuestiones de alcance que tiene, pero No sé por qué este fragmento no funciona. ¿Alguna idea?

Respuesta

82

cambiar esta línea:

t = timeit.Timer("foo()") 

A esto:

t = timeit.Timer("foo()", "from __main__ import foo") 

consulte el enlace que ya ha proporcionado en la parte inferior.

To give the timeit module access to functions you define, you can pass a setup parameter which contains an import statement:

Acabo de probarlo en mi máquina y funcionó con los cambios.

+20

Funciona! Sin embargo, este es un diseño de interfaz bastante estúpido si tengo que proporcionar el comando Deseo cronometrar como una cadena e importar el módulo __main__ para que funcione. –

+2

El espacio de nombres de Python es una absoluta locura para mí. Supongo que tiene sentido para cierto tipo de mente, pero esa clase de mente no es una de las que poseo. Gracias $ DEITY por Ruby, en mi caso. – womble

+4

womble, esto es una verruga, no es un problema general de espacio de nombres python. Tema principal: http://writeonly.wordpress.com/2008/09/12/using-python-timeit-to-time-functions/ tiene enlaces a otras discusiones sobre esto. –

8
t = timeit.Timer("foo()", "from __main__ import foo") 

Dado que timeit no tiene su material en el alcance.

18

Usted puede intentar este truco:

import timeit 

def foo(): 
    print 'bar' 

def dotime(): 
    t = timeit.Timer("foo()") 
    time = t.timeit(1) 
    print "took %fs\n" % (time,) 

import __builtin__ 
__builtin__.__dict__.update(locals()) 

dotime() 
+1

Este hack es genial si de otro modo necesitarías un código de configuración complejo. –

+0

Mejor que la alternativa del código de inicio dada en otras respuestas (es decir, mejor que 't = timeit.Timer (" foo() "," de __main__ import foo ")'). ¡Especialmente si quiere probar varias funciones diferentes, ahorrará mucho tipeo! –

+1

Tengo alrededor de 20 importaciones, por lo que pasarlas como argumento se complica rápidamente. ¡Este hack es increíble! – kramer65

0

Añadir a su configuración "thisfile importación;"

a continuación, cuando se llama a la función de configuración myfunc() utilizan "thisfile.myfunc()"

por ejemplo, "thisfile.py"

def myfunc(): 

return 5 

def testable(par): 

pass 



t=timeit.timeit(stmt="testable(v)",setup="import thisfile; v=thisfile.myfunc();").repeat(10) 

print(t) 
4

puede utilizar globals=globals()

t = timeit.Timer("foo()", globals=globals()) 

Desde el documentation:

Another option is to pass globals() to the globals parameter, which will cause the code to be executed within your current global namespace. This can be more convenient than individually specifying imports

+1

Works for Python 3 only. 'globals' no es un parámetro para' timeit' de Python 2 –

Cuestiones relacionadas