Mendapatkan "nama global 'foo' tidak ditentukan" dengan timeit Python

92

Saya mencoba mencari tahu berapa banyak waktu yang diperlukan untuk mengeksekusi pernyataan Python, jadi saya mencari online dan menemukan bahwa perpustakaan standar menyediakan modul yang disebut waktu yang dimaksudkan untuk melakukan hal itu:

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

Namun, ini menghasilkan kesalahan:

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

Saya masih baru mengenal Python dan saya tidak sepenuhnya memahami semua masalah cakupan yang dimilikinya, tetapi saya tidak tahu mengapa cuplikan ini tidak berfungsi. Ada pemikiran?

Kyle Cronin
sumber

Jawaban:

93

Ubah baris ini:

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

Untuk ini:

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

Lihat tautan yang Anda berikan di bagian paling bawah.

Untuk memberikan akses modul timeit ke fungsi yang Anda tentukan, Anda dapat memberikan parameter pengaturan yang berisi pernyataan import:

Saya baru saja mengujinya di mesin saya dan berhasil dengan perubahan.

Paolo Bergantino
sumber
28
Berhasil! Namun, ini adalah desain antarmuka yang cukup bodoh jika saya harus memberikan perintah yang saya ingin waktu sebagai string dan mengimpor modul utama agar berfungsi.
Kyle Cronin
2
Namespacing Python adalah kegilaan bagi saya. Saya berasumsi bahwa itu masuk akal untuk jenis pikiran tertentu, tetapi pikiran semacam itu bukanlah yang kebetulan saya miliki. Terima kasih $ DEITY untuk Ruby, dalam kasus saya.
womble
5
womble, ini adalah kutil, bukan masalah namespace python umum. Utas utama: writeonly.wordpress.com/2008/09/12/… memiliki tautan ke diskusi lain tentang ini.
Gregg Lind
1
@Gregg Tautan tidak lagi dapat diakses (kesalahan 404). Apa yang ada dalam diskusi itu?
ovgolovin
2
link-link tersebut semuanya dead
endolith
25

Dengan Python 3, Anda dapat menggunakan globals=globals()

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

Dari dokumentasi :

Opsi lainnya adalah meneruskan globals()ke globalsparameter, yang akan menyebabkan kode dijalankan dalam namespace global Anda saat ini. Ini bisa lebih nyaman daripada menentukan impor satu per satu

pengguna2314737
sumber
3
Bekerja untuk Python 3 saja. globalsbukan parameter untuk Python 2timeit
tony_tiger
21

Anda dapat mencoba retasan ini:

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()
Luka Zakrajšek
sumber
1
Peretasan ini bagus jika Anda memerlukan kode penyiapan yang rumit.
Luís Marques
Lebih baik daripada alternatif kode startup yang diberikan dalam balasan lain (yaitu lebih baik daripada t = timeit.Timer("foo()", "from __main__ import foo")). Khususnya jika Anda ingin menguji beberapa fungsi berbeda, ini akan menghemat banyak pengetikan!
A.Sommerh
1
Saya punya sekitar 20 impor, jadi meneruskannya sebagai argumen akan cepat berantakan. Retasan ini luar biasa!
kramer65
7
Bagus! Pada python3 bagaimanapun Anda membutuhkan import builtinsdan 'builtins .__ dict __. Update (lokal ())'
greole
Bisakah Anda mengatur waktu beberapa fungsi dalam fungsi Time ()?
edo101
8
t = timeit.Timer("foo()", "from __main__ import foo")

Sejak waktu itu tidak memiliki barang-barang Anda dalam ruang lingkup.

dwc
sumber
0

tambahkan ke dalam pengaturan Anda "import thisfile;"

lalu ketika Anda memanggil fungsi setup myfunc () gunakan "thisfile.myfunc ()"

misalnya "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 )
mist42nz.dll
sumber