Python: Почему планировщик событий продолжает дрейфовать, и есть ли способ это исправить? - PullRequest
0 голосов
/ 22 октября 2018

Я хочу использовать планировщик в графическом интерфейсе tkinter для секундомера.Я не уверен, что это лучшая идея, чем использование фонового потока, но я прочитал, что вы не должны останавливать потоки, тогда как я хотел постоянно запускать и останавливать функцию.

Я сделал небольшой фрагмент кодав Python 2.7 для проверки планировщика, и кажется, что он начинает дрейфовать немедленно.Я хотел, чтобы счетчик увеличивался каждую секунду, но на одну минуту я отключился на две секунды (вместо 60 секунд прошло 62 секунды).

Связана ли эта машина?Что-то не так с моим кодом?Должен ли я использовать другую библиотеку?

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()

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

Используйте 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
0 голосов
/ 22 октября 2018

Никогда не используйте задержку, если ваша цель - идти в ногу с реальным временем на большом расстоянии.

Всегда будет задержка, и в конечном итоге вы будете вне времени, причина этого - ненулевой процессорработать между началом события и планированием нового события, плюс у вас всегда есть приоритет задачи.

Итак, если вы хотите иметь задержку - используйте интерфейсы с интерфейсами run_after (в случае sched, .enter).Если вы хотите запланировать события - используйте «run_at» (.enterabs в вашем случае).Кстати, принимая во внимание, что у вас есть только один процесс в Python, вы все равно можете быть "поздним", но это не то, на что вы можете повлиять.

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

...