Измерение задержки смены фона и воспроизведения звука с помощью Timeit (python)

Мне нужно выяснить задержку между отправкой команды на изменение цвета фона или воспроизведением звука и этими событиями, фактически происходящими с помощью timeit. (У меня Windows, Python 2.73)
Я провожу тест времени реакции, где Я буду записывать время (используя time.clock()) перед тем, как изменить цвет фона или воспроизвести звук. Затем, когда субъект нажимает клавишу, я снова записываю время и определяю время реакции по разнице.
Что касается воспроизведения звука, я сделал следующее:

import timeit
t = timeit.Timer(stmt = "winsound.PlaySound('C:\WINDOWS\media\Windows XP Error.wav', winsound.SND_FILENAME)",setup = "import winsound")
n = t.timeit(number = 100) 
print n/100 -0.999  

0,999 — это продолжительность файла Windows XP Error.wav в секундах.
Это дало мне около 56 мс. Я не уверен, что это разумно и правильно ли это сделать, а также должен ли я включать сборку мусора или нет?


Для смены фона у меня больше проблем. Поскольку я выполняю тест в полноэкранном режиме, я попытался поместить все это в параметр настройки:

from Tkinter import Tk
root=Tk()
root.overrideredirect(True)
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(),root.winfo_screenheight()))
root.mainloop()

Хотя я разделяю их все с помощью ; Я все еще получаю синтаксические ошибки. Когда я пробую это не в полноэкранном режиме
setup = 'from Tkinter import Tk; root=Tk(); root.mainloop()', окно фактически открывается, но ничего не происходит, и если я закрою его, я увижу другие ошибки.Invalid command name "."
Утверждение, которое я фактически измеряю, это root.configure(background='red').


person user1830663    schedule 17.11.2012    source источник
comment
Какая у вас версия Python? Если он не слишком старый, вы можете передать функцию timeit вместо строки. Если вы не можете этого сделать, попробуйте разделить строки с помощью \n вместо ;.   -  person abarnert    schedule 17.11.2012
comment
Между тем, время этих функций будет сильно различаться от одной машины к другой. На вашей машине это может занять 56 мс, а на моей — 496 мс. Итак, если вы планируете просто жестко закодировать эти 56 в своей программе, это никому не будет полезно.   -  person abarnert    schedule 17.11.2012
comment
@abarnert Я использую 2.7.3. \n выдал ту же ошибку. Я не совсем уверен, как передать функцию timeit, но если это сделать, не будет ли она также запускаться каждый раз, когда все эти вещи, которые я включил в настройку?   -  person user1830663    schedule 17.11.2012
comment
Тайминг буду делать на той машине с которой буду тестировать(всего 1). Есть ли у вас какие-либо идеи о том, следует ли мне использовать сборку мусора или нет? Я не совсем понимаю, что это меняет.   -  person user1830663    schedule 17.11.2012
comment
Чтобы передать функцию, вы просто передаете функцию вместо строки и обычно не используете настройку. Например, pastebin.com/WF4m2yQm эквивалентен вашей первой версии, а pastebin.com/xhH61Ntp эквивалентен тому, что, как я думаю, должен быть ваш второй. Конечно, если вы хотите, чтобы тест выполнялся внутри mainloop, а не перед ним, вы должны ввести его в цикл, каким-то образом запустив его внутри Tkinter (как предлагает Мартино в комментарии к своему ответу).   -  person abarnert    schedule 20.11.2012
comment
PS, похоже, вы хотите, чтобы это произошло после mainloop, что не имеет никакого смысла. После того, как он вернется, Tk будет отключен, и вы больше не сможете на него звонить.   -  person abarnert    schedule 20.11.2012


Ответы (1)


Вот пример создания многострочной строки установки для использования с timeit:

setup = """
import random
l1 = [random.randrange(100) for _ in xrange(100)]
l2 = [random.randrange(100) for _ in xrange(10)]
"""

Вот еще один совет. Чтобы получить точные измерения, важно рассчитать время по следующему основному шаблону:

time = min(timeit.repeat(statements, setup=setup, repeat=R, number=N))

С R не ниже 3 (R = 3). Это берет самое быстрое значение, полученное при выполнении всего 3 раза, что устранит различия из-за многих других вещей, работающих в вашей системе в фоновом режиме.

Это не отвечает на весь ваш вопрос, но может быть полезно в ваших поисках.

person martineau    schedule 17.11.2012
comment
Кажется, это решает проблему с синтаксисом, но я все еще получаю invalid command name "." - person user1830663; 17.11.2012
comment
Вероятно, это из-за обратной косой черты в аргументе PlaySound. Сделайте его необработанной строкой, добавив префикс r, например r'C:\WINDOWS\media\Windows XP Error.wav'. - person martineau; 17.11.2012
comment
Этот на самом деле работает нормально, его фон меняется, а не меняется. Я только что добавил эти 3 строки import timeit t = timeit.Timer(stmt = "root.configure(background = 'red')", setup = setup) print t.timeit() в вашу многострочную строку настройки. - person user1830663; 17.11.2012
comment
Вам не нужен оператор print t.timeit() в строке установки. На самом деле, import и создание объекта Timer туда тоже не поместишь. - person martineau; 17.11.2012
comment
Они не находятся внутри строки установки. Моя первая строка import timeit, затем строка настройки, в которой я помещаю все 5 параметров, как в моем первом посте, а затем объект таймера и печать. Извините за путаницу. - person user1830663; 17.11.2012
comment
Хорошо, извините за недоразумение. root.mainloop() неудивительно, что это цикл. Когда вы помещаете это в свою строку установки и она выполняется, она не заканчивается до тех пор, пока не закроется главное окно и не завершится mainloop. Я не эксперт по tkinter, но считаю, что вам придется замерять время внутри mainloop, вероятно, в результате какого-то события, например нажатия клавиши или кнопки. - person martineau; 17.11.2012
comment
@martineau: Или, если у него есть основной цикл, который просто воспроизводит звук, а затем завершает работу, может быть, сделать root.mainloop() временную инструкцию вместо части настройки? - person abarnert; 19.11.2012
comment
@abarnert: Потому что mainloop() выполняет множество довольно трудоемких вещей, которые не являются частью того, что пытается измерить OP. - person martineau; 20.11.2012
comment
@martineau: Ну, он мог вычесть результаты двух вызовов mainloop, одного с функцией и одного без нее. (Учитывая его вариант использования, сколько времени это займет на этой конкретной машине в этом конкретном сценарии, это может быть разумным.) Но да, в противном случае ему придется поместить время в mainloop скорее чем на верхнем уровне, как вы предлагаете. - person abarnert; 20.11.2012
comment
@abarnert: Это может сработать. С другой стороны, предложенный мной способ не слишком отличается от реального написания приложения, поэтому часть кода для этой работы может быть повторно использована или может уже существовать. - person martineau; 20.11.2012