【问题标题】:custom timeit, from __main__ import everything necessary自定义 timeit,从 __main__ 导入所有必要的
【发布时间】:2021-08-23 19:54:01
【问题描述】:

魔术命令%timeit 不是在脚本中使用的。

在Use Python's `timeit` from a program but functioning the same way as the command line?中,用户Unutbu提出了以下功能:

import timeit

def timeit_auto(stmt="pass", setup="pass", repeat=3):
    """
    http://stackoverflow.com/q/19062202/190597 (endolith)
    Imitate default behavior when timeit is run as a script.

    Runs enough loops so that total execution time is greater than 0.2 sec,
    and then repeats that 3 times and keeps the lowest value.

    Returns the number of loops and the time for each loop in microseconds
    """
    t = timeit.Timer(stmt, setup)

    # determine number so that 0.2 <= total time < 2.0
    for i in range(1, 10):
        number = 10**i
        x = t.timeit(number) # seconds
        if x >= 0.2:
            break
    r = t.repeat(repeat, number)
    best = min(r)
    usec = best * 1e6 / number
    return number, usec

可以如下使用:

import timeit
import utils_timeit as UT

def foo():
    total = 0
    for i in range(10000):
        total += i**3
    return total

num, timing = UT.timeit_auto(setup='from __main__ import foo', stmt='foo()')
print(num, timing)

这是一个非常聪明和方便的解决方案。但是,我正在寻找更好的方法。我不想给函数一个setup 声明,我认为这很讨厌。如果我有一个数据框df 和一个列名column_name_a,我不想在我想为df[column_name_a] 计时操作时明确声明setup='from __main__ import df, column_name_a'。

有什么好的方法可以解决吗?我自己通过将它添加到函数中来完成它,以便通过捕获错误将所有需要的变量添加到循环中的 setup 语句中:

condition = True

setup = 'from __main__ import _'

while condition:
    try:
        t = timeit.Timer(stmt, setup)
        t.repeat(repeat, number)
        condition = False
    except NameError as err:
        str_err = str(err)
        extra_import = str_err.split(sep="'")[1]
        setup = setup + ', ' + extra_import

这当然不是一个非常微妙的解决方案。有没有人有更好的方法?

此外,在同一个线程(Use Python's `timeit` from a program but functioning the same way as the command line?)中,有人提议使用Timer.autorange 方法。我不确定如何将其包含在函数中。谁能帮我解决这个问题?

【问题讨论】:

    标签: python timeit


    【解决方案1】:

    timeit.Timer 对象从 python 3.5 开始接受 globals 参数,这允许您直接使用模块命名空间。 autorange方法是python 3.6新增的,是Untubu's solution的正式版。

    您可以通过以下方式将它们组合在一起:

    >>> from timeit import Timer
    >>> def foo(): ...
    >>> num, timing = Timer(stmt='foo()', globals=globals()).autorange()
    

    从 python 3.6 开始,您可以直接将 timeit.Timer 对象用于这个确切的应用程序。如果你有3.5版本,可以修改Untubu的解决方案如下:

    def timeit_auto(stmt="pass", setup="pass", repeat=3, globals=None):
        t = timeit.Timer(stmt, setup, globals=globals())
        ...
    

    【讨论】:

      猜你喜欢
      • 2015-09-10
      • 2014-04-19
      • 2021-08-25
      • 2019-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-25
      • 1970-01-01
      相关资源
      最近更新 更多