Я хочу использовать планировщик в графическом интерфейсе tkinter для секундомера. Я не уверен, что это лучше, чем использование фонового потока, но я читал, что вы не должны останавливать потоки, тогда как я хотел постоянно запускать и останавливать функцию.
Я сделал небольшой фрагмент кода в Python 2.7, чтобы протестировать планировщик, и кажется, что он сразу же начинает дрейфовать. Я хотел, чтобы счетчик увеличивался каждую секунду, но к одной минуте я отключаюсь на две секунды (прошло 62 секунды вместо 60 секунд).
Связана ли эта машина? Что-то не так с моим кодом? Стоит ли использовать другую библиотеку?
import sched, time
class Scheduler_Test:
def __init__(self):
self.counter = 0
self.time_increment = 1.0
self.end_time = 0.0
self.s = sched.scheduler(time.time, time.sleep)
self.start_time = time.time()
self.s.enter(self.time_increment, 1, self.do_something, (self.s,))
self.s.run() # run the event scheduler
#Simple test of printing out the computer time (sec) and count
def do_something(self, random_kwarg):
print "Time (sec):",time.time(),", count:", self.counter
self.event = self.s.enter(self.time_increment, 1, self.do_something, (random_kwarg,))
self.counter = self.counter + 1
Test = Scheduler_Test()
jasonharper, разве это не срабатывает только в указанное время? docs.python.org/2/library/sched.html
Никогда не используйте задержку, если ваша цель - не отставать от реального времени на большом расстоянии.
Всегда будет задержка, и, в конце концов, вы выйдете не по расписанию, причина этого в том, что между запуском события и планированием нового события есть ненулевая нагрузка на ЦП, плюс у вас всегда есть приоритет задачи.
Итак, если вы хотите иметь задержку - используйте интерфейсы с интерфейсами run_after (в случае sched
, .enter
). Если вы хотите что-то запланировать - используйте run_at (в вашем случае .enterabs
). Кстати, учитывая, что у вас есть только один процесс в python, вы все равно будете «опаздывать», но это не то, на что вы можете повлиять.
Боковое примечание: вы редко хотите переопределять таймеры планировщика, значения по умолчанию в порядке, он использует time.monotonic
с откатом на time.time
. Монотонность избавит вас от неожиданной боли, если ваш код будет использоваться в реальном мире.
Для этой команды "enterabs" вы говорите, что я буду продолжать указывать более позднее / новое системное время. Например, если время было 1540304695, и я хотел, чтобы он сработал на секунду позже, я бы продолжал увеличивать и запускал 1540304696?
Если вы хотите, чтобы "~ 1 секунда позже текущего времени" - используйте задержку / ввод, если вам это нужно в определенное время - да, enterabs(now + delta)
. Это звучит странно, но имейте в виду, что любая операция / строка кода - это не бесплатно с точки зрения времени.
Используйте time.time
, чтобы на самом деле отсчитывать время. Вы можете обновить пользовательский интерфейс с помощью часов tkinter, но обновите его до значения дельты времени с момента запуска таймера.
Я сделал аналогичное приложение, используя PySimpleGUI, который основан на tkinter. Я рассчитал время следующим образом ... псевдокод следует, поскольку я использую оболочку для выполнения этих функций ...
start_time = int(round(time.time() * 100))
while True:
# use timer using tkinter's 'after' method
# tkroot.after(timeout, alarmcallback) (Pseudocode)
# tkroot.mainloop()
# in the alarm callback I called quit tkroot.quit()
# Then I'm back in my code....
current_time = int(round(time.time() * 100)) - start_time
# Update the GUI with current_time
Если вам нужна точная синхронизация, вам следует использовать
.enterabs()
вместо.enter()
.