Python'un timeit ile "global isim 'foo' tanımlanmadı


92

Bir Python ifadesini çalıştırmanın ne kadar zaman aldığını bulmaya çalışıyorum, bu yüzden çevrimiçi baktım ve standart kitaplığın tam olarak bunu yapmak için timeit adında bir modül sağladığını gördüm :

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

Ancak bu bir hataya neden olur:

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

Python'da hala yeniyim ve sahip olduğu kapsam belirleme sorunlarını tam olarak anlamıyorum, ancak bu kod parçacığının neden çalışmadığını bilmiyorum. Düşüncesi olan var mı?

Yanıtlar:


93

Bu satırı değiştirin:

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

Buna:

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

En altta sağladığınız bağlantıya bakın.

Timeit modülüne tanımladığınız işlevlere erişim vermek için, bir import deyimi içeren bir kurulum parametresi iletebilirsiniz:

Sadece makinemde test ettim ve değişikliklerle çalıştı.


28
İşe yarıyor! Ancak, hem zamanlamak istediğim komutu bir dizge olarak sağlamam hem de çalışması için ana modülü içe aktarmam gerekirse, bu oldukça aptalca bir arayüz tasarımı .
Kyle Cronin

2
Python ad aralığı benim için tam bir çılgınlık. Bunun belirli bir zihin için anlamlı olduğunu varsayıyorum, ama bu tür bir zihin benim sahip olduğum bir zihin değil. Benim durumumda Ruby için $ DEITY'ye teşekkür et.
womble

5
womble, bu bir siğil, genel bir python isim-alanı problemi değil. Ana konu: writeonly.wordpress.com/2008/09/12/… , bununla ilgili diğer tartışmalara bağlantılar içerir.
Gregg Lind

1
@Gregg Bağlantı artık erişilebilir değil (hata 404). O tartışmada ne vardı?
ovgolovin

2
bu bağlantıların hepsi çıkmaz
endolith

25

Python 3 ile şunları kullanabilirsiniz: globals=globals()

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

Gönderen belgeler :

Başka bir seçenek geçmektir globals()için globalskod geçerli genel ad dahilinde yürütülecek neden olacaktır parametresi. Bu, ithalatı ayrı ayrı belirtmekten daha uygun olabilir


3
Yalnızca Python 3 için çalışır. globalsPython timeit
2'ler

21

Bu hack'i deneyebilirsiniz:

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
Aksi takdirde karmaşık kurulum koduna ihtiyacınız varsa bu hack harikadır.
Luís Marques

Diğer yanıtlarda verilen başlangıç ​​kodu alternatifinden daha iyi (yani daha iyi t = timeit.Timer("foo()", "from __main__ import foo")). Özellikle birkaç farklı işlevi test etmek istiyorsanız, çok fazla yazmadan tasarruf sağlayacaktır!
A.Sommerh

1
Yaklaşık 20 ithalatım var, bu yüzden onları bir argüman olarak geçmek karmaşıklaşıyor. Bu hack harika!
kramer65

7
Harika! Ancak python3'te import builtins'builtins .__ dict __. Update (locals ())' a ihtiyacınız var
greole

Time () işlevinde birden çok işlevi zamanlayabilir misiniz?
edo101

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

Zamandan beri, kapsamda eşyalarınız yok.


0

kurulumunuza ekleyin "bu dosyayı içe aktarın;"

daha sonra kurulum işlevini çağırdığınızda myfunc () "thisfile.myfunc ()" kullanın

örneğin "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 )
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.