Как заставить модуль Python timeit не повторять последнюю итерацию в цикле

Я делаю нагрузочное тестирование, используя timeit. Я просматриваю список. Во всем, что я пробовал, timeit повторяет последнее значение в списке 3 раза. Я знаю, что повтор по умолчанию равен 3. Я пробовал не использовать повтор. Я пытался использовать повтор, но установил для повтора значение 0. Я хочу либо 0 повторов, либо повтор, который выбирает правильный параметр вместо повторения последнего параметра 3 раза. Я покажу вам, что я пробовал, а затем ожидаемые результаты и фактические результаты.

Мой модуль называется z_sandbox.py, и я вызываю его в модуле, выполняя в VS Code. Я не использую командную строку.

Я пробовал три разных варианта:

Вариант 1: timeit.Timer без указания повторов.

import timeit
params = ["param1", "param2", "param3"]
print("*****START*****")
for param in params:  
    print('STARTING: %s ' % (param))   
    timeit.Timer(
        stmt="print('%s ' % (z_sandbox.param))",
        setup="import z_sandbox"
    ).timeit(number=3)
print("*****DONE*****")

Ожидаемые результаты:

В приведенном выше я не использую повтор, поэтому я не ожидаю повторений и ровно 3 выполнения каждого оператора, всего 9 выполнений.

Ожидается:

*****START*****
STARTING: param1
param1
param1
param1
STARTING: param2
param2
param2
param2
STARTING: param3
param3
param3
param3
*****DONE*****

Факт:

*****START*****
STARTING: param1
*****START*****
STARTING: param1
param1
param1
param1
STARTING: param2
param2
param2
param2
STARTING: param3
param3
param3
param3
*****DONE*****
param3
param3
param3
STARTING: param2
param3
param3
param3
STARTING: param3
param3
param3
param3
*****DONE*****

Вопросы: Почему "STARTING: param1" печатается дважды вверху? Почему последние 9 выполнений всех param3 вместо 3-х исполнений каждого параметра? Почему в повторах есть «НАЧАЛО: param2», но тогда фактическое выполнение было для param3? Как мне получить ожидаемые результаты, которые не повторяются?

Вариант №2: timeit.repeat, указан 1 повтор.

timeit.repeat(
    stmt="print('%s ' % (z_sandbox.param))",
    setup="import z_sandbox",
    repeat=1,
    number=3
)

Выше приведены те же результаты, что и в варианте № 1.

Вариант № 3: timeit.repeat с указанным 0 повторений.

timeit.repeat(
    stmt="print('%s ' % (z_sandbox.param))",
    setup="import z_sandbox",
    repeat=0,
    number=3
)

Выше вообще ничего не производит.

Варианты каждого из вышеперечисленных

Я также попытался распечатать вывод в файл, а не на экран. На выходе разницы нет.

Как мне получить ожидаемые результаты, которые не повторяются?


person Kelby    schedule 04.12.2019    source источник


Ответы (1)


Вы можете передать вызываемый объект как stmt в Timer.

timeit.Timer(stmt=lambda: print('%s ' % (param,))).timeit(number=3)

Проблема с вашим кодом заключалась в том, что у него не было основной защиты импорта, чтобы предотвратить появление основного кода при повторном импорте модуля. Особенность основных модулей в том, что их можно загружать дважды. Один раз как __main__ и один раз под именем своего модуля.

Ваш код можно исправить, выполнив:

import timeit
params = ["param1", "param2", "param3"]
if __name__=="__main__":
    print("*****START*****")
    for idx, param in enumerate(params): 
        print('STARTING: %s ' % (param,)) 
        timeit.Timer(stmt="print('%%s ' %% (z_sandbox.params[%r]))" % (idx,), setup="import z_sandbox" ).timeit(number=3)
    print("*****DONE*****")
person Dan D.    schedule 04.12.2019