Das Erhalten des "globalen Namens 'foo' ist nicht definiert" mit Pythons Zeit


89

Ich versuche herauszufinden, wie viel Zeit es dauert, eine Python-Anweisung auszuführen. Deshalb habe ich online nachgesehen und festgestellt, dass die Standardbibliothek ein Modul namens timeit bereitstellt , das genau das vorgibt:

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

Dies führt jedoch zu einem Fehler:

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

Ich bin noch neu in Python und verstehe nicht alle Scoping-Probleme, aber ich weiß nicht, warum dieses Snippet nicht funktioniert. Irgendwelche Gedanken?

Antworten:


93

Ändern Sie diese Zeile:

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

Dazu:

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

Schauen Sie sich den Link an, den Sie ganz unten angegeben haben.

Um dem timeit-Modul Zugriff auf von Ihnen definierte Funktionen zu gewähren, können Sie einen Setup-Parameter übergeben, der eine import-Anweisung enthält:

Ich habe es gerade auf meinem Computer getestet und es hat mit den Änderungen funktioniert.


28
Es klappt! Dies ist jedoch ein ziemlich dummes Schnittstellendesign, wenn ich sowohl den Befehl, den ich zeitlich festlegen möchte, als Zeichenfolge angeben als auch das Hauptmodul importieren muss, damit es funktioniert.
Kyle Cronin

2
Python-Namespace ist für mich völliger Wahnsinn. Ich gehe davon aus, dass es für eine bestimmte Art von Geist Sinn macht, aber diese Art von Geist ist nicht einer, den ich zufällig besitze. Vielen Dank an $ DEITY für Ruby in meinem Fall.
Womble

5
Womble, dies ist eine Warze, kein allgemeines Python-Namespace-Problem. Hauptthread: writeonly.wordpress.com/2008/09/12/… enthält Links zu anderen Diskussionen darüber.
Gregg Lind

1
@ Gregg Der Link ist nicht mehr zugänglich (Fehler 404). Was war in dieser Diskussion?
Ovgolovin


24

Mit Python 3 können Sie verwenden globals=globals()

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

Aus der Dokumentation :

Eine andere Möglichkeit besteht darin, globals()an den globalsParameter zu übergeben, wodurch der Code in Ihrem aktuellen globalen Namespace ausgeführt wird. Dies kann bequemer sein, als Importe einzeln anzugeben


3
Funktioniert nur für Python 3. globalskein Parameter für Python 2timeit
tony_tiger

21

Sie können diesen Hack versuchen:

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
Dieser Hack ist großartig, wenn Sie sonst komplexen Setup-Code benötigen.
Luís Marques

Besser als die in anderen Antworten angegebene Startcode-Alternative (dh besser als t = timeit.Timer("foo()", "from __main__ import foo")). Insbesondere wenn Sie mehrere verschiedene Funktionen testen möchten, sparen Sie viel Tipparbeit!
A. Sommerh

1
Ich habe ungefähr 20 Importe, daher wird es schnell chaotisch, sie als Argument zu übergeben. Dieser Hack ist großartig!
kramer65

7
Toll! Auf Python3 jedoch benötigen Sie import builtinsund 'eingebaute .__ dikt __. Update (Locals ())'
Greole

Können Sie mehrere Funktionen in der Funktion Time () zeitlich festlegen?
edo101

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

Da hat timeit deine Sachen nicht im Umfang.


0

füge in dein Setup "import thisfile;"

Wenn Sie dann die Setup-Funktion myfunc () aufrufen, verwenden Sie "thisfile.myfunc ()".

zB "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 )
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.