Last active
February 28, 2024 02:59
-
-
Save cypreess/5481681 to your computer and use it in GitHub Desktop.
Python periodic thread using timer. You can cancel this thread any time. Thread will live at maximum to the end of one single processing run, otherwise it will end in the same time (especially during a wait time for next run). This code avoids the problem of waiting very long for thread exiting, because it does not uses time.sleep(). Please be a…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import threading | |
class PeriodicThread(object): | |
""" | |
Python periodic Thread using Timer with instant cancellation | |
""" | |
def __init__(self, callback=None, period=1, name=None, *args, **kwargs): | |
self.name = name | |
self.args = args | |
self.kwargs = kwargs | |
self.callback = callback | |
self.period = period | |
self.stop = False | |
self.current_timer = None | |
self.schedule_lock = threading.Lock() | |
def start(self): | |
""" | |
Mimics Thread standard start method | |
""" | |
self.schedule_timer() | |
def run(self): | |
""" | |
By default run callback. Override it if you want to use inheritance | |
""" | |
if self.callback is not None: | |
self.callback() | |
def _run(self): | |
""" | |
Run desired callback and then reschedule Timer (if thread is not stopped) | |
""" | |
try: | |
self.run() | |
except Exception, e: | |
logging.exception("Exception in running periodic thread") | |
finally: | |
with self.schedule_lock: | |
if not self.stop: | |
self.schedule_timer() | |
def schedule_timer(self): | |
""" | |
Schedules next Timer run | |
""" | |
self.current_timer = threading.Timer(self.period, self._run, *self.args, **self.kwargs) | |
if self.name: | |
self.current_timer.name = self.name | |
self.current_timer.start() | |
def cancel(self): | |
""" | |
Mimics Timer standard cancel method | |
""" | |
with self.schedule_lock: | |
self.stop = True | |
if self.current_timer is not None: | |
self.current_timer.cancel() | |
def join(self): | |
""" | |
Mimics Thread standard join method | |
""" | |
self.current_timer.join() | |
There should also be a self.stop = False
just before line 24
so that the timer can get restarted after it was stopped with cancel().
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks! Works a treat. Was struggling to achieve this functionality with the fundamental threading.Timer, then stumbled across your work.