Использовать Python `timeit` из программы, но функционировать так же, как командная строка?
Например, документация гласит:
Однако обратите внимание, что timeit будет автоматически определять количество повторений только при использовании интерфейса командной строки.
Есть ли способ вызвать его из скрипта Python и автоматически определить количество повторений, при этом возвращается только самое короткое число?
1 ответ
Когда вы звоните timeit
из командной строки вот так:
python -mtimeit -s'import test' 'test.foo()'
timeit
Модуль называется скриптом. В частности, main
функция называется:
if __name__ == "__main__":
sys.exit(main())
Если вы посмотрите на исходный код, вы увидите, что main
функция может занять args
аргумент:
def main(args=None):
if args is None:
args = sys.argv[1:]
Так что действительно можно бежать 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()'"""))
напечатает что-то вроде
100 loops, best of 3: 7.9 msec per loop
К несчастью, main
печатает на консоль, а не возвращает время за цикл. Поэтому, если вы хотите программно использовать результат, возможно, самый простой способ - начать с копирования main
функция, а затем ее изменение - изменение кода печати, чтобы вместо возврата usec
,
Пример по OP: если вы разместите это в utils_timeit.py
:
import timeit
def timeit_auto(stmt="pass", setup="pass", repeat=3):
"""
http://stackru.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)
Начиная с Python 3.6, timeit.Timer
объекты имеют autorange
функция, которая показывает, как number
определяется для выполнения из командной строки.