Ottenere "nome globale 'foo' non è definito" con timeit di Python


92

Sto cercando di scoprire quanto tempo ci vuole per eseguire un'istruzione Python, quindi ho cercato online e ho scoperto che la libreria standard fornisce un modulo chiamato timeit che pretende di fare esattamente questo:

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()

Tuttavia, questo produce un errore:

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

Sono ancora nuovo in Python e non capisco appieno tutti i problemi di scoping che ha, ma non so perché questo frammento non funziona. qualche idea?

Risposte:


93

Cambia questa riga:

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

A questo:

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

Controlla il link che hai fornito in fondo.

Per dare al modulo timeit l'accesso alle funzioni definite, è possibile passare un parametro di configurazione che contiene un'istruzione import:

L'ho appena testato sulla mia macchina e ha funzionato con le modifiche.


28
Funziona! Tuttavia, questo è un progetto di interfaccia piuttosto stupido se devo sia fornire il comando che desidero cronometrare come una stringa sia importare il modulo principale affinché funzioni.
Kyle Cronin,

2
Il namespace di Python è una follia assoluta per me. Presumo che abbia senso per un certo tipo di mente, ma quel tipo di mente non è quello che mi capita di possedere. Grazie a $ DEITY per Ruby, nel mio caso.
womble

5
womble, questa è una verruca, non un problema generale dello spazio dei nomi di Python. Thread principale: writeonly.wordpress.com/2008/09/12/… contiene collegamenti ad altre discussioni su questo argomento.
Gregg Lind,

1
@ Gregg Il collegamento non è più accessibile (errore 404). Cosa c'era in quella discussione?
ovgolovin

2
quei collegamenti sono tutti morti
endolith

25

Con Python 3, puoi usare globals=globals()

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

Dalla documentazione :

Un'altra opzione è passare globals()al globalsparametro, che farà eseguire il codice all'interno dello spazio dei nomi globale corrente. Questo può essere più conveniente che specificare singolarmente le importazioni


3
Funziona solo per Python 3. globalsnon è un parametro per Python 2timeit
tony_tiger

21

Puoi provare questo trucco:

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
Questo trucco è ottimo se altrimenti avresti bisogno di un codice di configurazione complesso.
Luís Marques

Migliore dell'alternativa al codice di avvio fornita in altre risposte (cioè migliore di t = timeit.Timer("foo()", "from __main__ import foo")). Specialmente se vuoi testare diverse funzioni, risparmierai un sacco di digitazione!
A.Sommerh

1
Ho circa 20 importazioni, quindi passarle come argomento diventa complicato rapidamente. Questo trucco è fantastico!
kramer65

7
Grande! Su python3 tuttavia è necessario import builtinse 'builtins .__ dict __. Update (locals ())'
greole

Puoi cronometrare più funzioni nella funzione Time ()?
edo101

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

Da tempo non ha le tue cose nell'ambito.


0

aggiungi nel tuo setup "importa questo file;"

quindi quando chiami la funzione di configurazione myfunc () usa "thisfile.myfunc ()"

ad esempio "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 )
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.