【问题标题】:Getting "global name 'foo' is not defined" with Python's timeit使用 Python 的 timeit 获取“未定义全局名称 'foo'”
【发布时间】:2010-10-07 19:09:33
【问题描述】:

我想知道执行一条 Python 语句需要多少时间,所以我上网查了一下,发现标准库提供了一个名为 timeit 的模块,声称可以做到这一点:

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

但是,这会产生错误:

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 的新手,我不完全理解它的所有范围问题,但我不知道为什么这个 sn-p 不起作用。有什么想法吗?

【问题讨论】:

    标签: python scope timeit


    【解决方案1】:

    使用 Python 3,您可以使用 globals=globals()

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

    来自documentation

    另一种选择是将globals() 传递给globals 参数,它 将导致代码在您当前的全局范围内执行 命名空间。这比单独指定更方便 进口

    【讨论】:

    • 仅适用于 Python 3。 globals 不是 Python 2 的 timeit 的参数
    • 我必须像这样合并 globalslocalsimports_and_vars=globals(); imports_and_vars.update(locals()) 然后像 t = timeit.Timer("foo()", globals=imports_and_vars) 一样传递它
    【解决方案2】:

    改变这一行:

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

    到这里:

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

    查看您在最底部提供的链接。

    要让 timeit 模块访问您定义的函数,您可以传递一个包含导入语句的设置参数:

    我刚刚在我的机器上对其进行了测试,并且它适用于所做的更改。

    【讨论】:

    • 有效!但是,如果我必须同时提供我希望作为字符串计时的命令并导入 main 模块以使其工作,那么这是一个非常愚蠢的界面设计。
    • Python 命名空间对我来说简直太疯狂了。我认为这对某种思想是有意义的,但这种思想不是我碰巧拥有的。就我而言,感谢 $DEITY 的 Ruby。
    • womble,这是一个疣,不是一般的 python 命名空间问题。主线程:writeonly.wordpress.com/2008/09/12/… 有其他讨论的链接。
    • 那些链接都失效了
    • 对于 Python 3,使用@user2314737 t = timeit.Timer("foo()", globals=globals()) 的解决方案
    【解决方案3】:

    在您的设置中添加“导入此文件;”

    然后当你调用设置函数 myfunc() 时使用“thisfile.myfunc()”

    例如“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】:

      你可以试试这个技巧:

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

      【讨论】:

      • 如果您需要复杂的设置代码,这个 hack 非常棒。
      • 优于其他回复中给出的启动代码替代方案(即优于t = timeit.Timer("foo()", "from __main__ import foo"))。特别是如果你想测试几个不同的功能,它会节省很多打字!
      • 我有大约 20 个导入,因此将它们作为参数传递会很快变得混乱。这个黑客太棒了!
      • 太棒了!但是,在 python3 上,您需要 import builtins 和 'builtins.__dict__.update(locals())'
      • 你能在 Time() 函数中为多个函数计时吗?
      【解决方案5】:
      t = timeit.Timer("foo()", "from __main__ import foo")
      

      因为 timeit 没有你的东西在范围内。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-02-18
        • 2017-03-27
        • 2017-02-03
        • 2013-08-23
        • 2013-11-12
        • 2014-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多