从程序中使用Python的`timeit`,但其功能与命令行相同?

end*_*ith 6 python timeit

例如,文档说:

但请注意,只有在使用命令行界面时,timeit才会自动确定重复次数.

有没有办法从Python脚本中调用它并自动确定重复次数,只返回最短的数字?

unu*_*tbu 8

当您timeit从命令行调用时,如下所示:

python -mtimeit -s'import test' 'test.foo()'
Run Code Online (Sandbox Code Playgroud)

timeit模块称为脚本.特别是,该main函数被称为:

if __name__ == "__main__":
    sys.exit(main())
Run Code Online (Sandbox Code Playgroud)

如果查看源代码,您会看到该main函数可以带args参数:

def main(args=None):    
    if args is None:
        args = sys.argv[1:]
Run Code Online (Sandbox Code Playgroud)

因此,确实可以timeit从程序中运行,其行为与从CLI运行时看到的行为完全相同.只需提供您自己的,args而不是将其设置为sys.argv[1:]:

import timeit
import shlex

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

timeit.main(args=shlex.split("""-s'from __main__ import foo' 'foo()'"""))
Run Code Online (Sandbox Code Playgroud)

会印出类似的东西

100 loops, best of 3: 7.9 msec per loop
Run Code Online (Sandbox Code Playgroud)

不幸的是,main打印到控制台,而不是返回每个循环的时间.所以,如果你想以编程方式使用的结果,也许是最简单的方法是通过复制来启动main功能,然后修改它-改变打印代码,改为返回usec.


OP的例子: 如果你把它放在utils_timeit.py:

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
Run Code Online (Sandbox Code Playgroud)

你可以在这样的脚本中使用它:

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)
Run Code Online (Sandbox Code Playgroud)