Skip to content

Instantly share code, notes, and snippets.

@TomFaulkner
Created February 11, 2018 00:28
Show Gist options
  • Save TomFaulkner/6a790051701c291f53c07de9192c7fb6 to your computer and use it in GitHub Desktop.
Save TomFaulkner/6a790051701c291f53c07de9192c7fb6 to your computer and use it in GitHub Desktop.
Python Perpetual (Repeating) Timer
"""
PerpetualTimer: Run a function every x seconds until PerpetualTimer.cancel().
Source, with some modificiations:
https://stackoverflow.com/questions/12435211/python-threading-timer-repeat-function-every-n-seconds
Example usage:
def printer():
print('ipsem lorem')
t = PerpetualTimer(3, printer)
t.start()
time.sleep(8)
t.cancel()
There is an issue of concern with this code. If the interval is relatively low
compared to the time it takes the handler_function to run much of the time will
be spent in the blocking function and .cancel will not work. Cancel will only
work while a timer is active and nothing is going on.
For example, if seconds=30 and handler_function is blocking for 10 seconds the
Timer will start for 30 seconds, then the handler_function will block for
twenty. The Timer, which is not blocked, will execute again 20 seconds after
the blocking function is done.
One potential solution is to have handler_function be a function that spawns a
thread.
"""
import time
from threading import Timer
class PerpetualTimer:
"""A Timer class that does not stop, unless you want it to."""
def __init__(self, seconds, target):
self._should_continue = False
self.is_running = False
self.seconds = seconds
self.target = target
self.thread = None
def _handle_target(self):
self.is_running = True
self.target()
self.is_running = False
print('handled target')
self._start_timer()
def _start_timer(self):
# Code could have been running when cancel was called.
if self._should_continue:
self.thread = Timer(self.seconds, self._handle_target)
self.thread.start()
def start(self):
if not self._should_continue and not self.is_running:
self._should_continue = True
self._start_timer()
def cancel(self):
if self.thread is not None:
# Just in case thread is running and cancel fails.
self._should_continue = False
self.thread.cancel()
if __name__ == '__main__':
# Example usage:
def printer():
print('ipsem lorem')
t = PerpetualTimer(3, printer)
t.start()
time.sleep(8)
t.cancel()
@linuxesdios
Copy link

y try cancel the thread and i cant
from threading import Timer,Thread,Event
import time
import RPi.GPIO as GPIO
import time

class perpetualTimer():

def init(self,t,hFunction):
self.t=t
self.hFunction = hFunction
self.thread = Timer(self.t,self.handle_function)

def handle_function(self):
self.hFunction()
self.thread = Timer(self.t,self.handle_function)
self.thread.start()

def start(self):
self.thread.start()

def cancel(self):
self.thread.cancel()

def apagar():
print ('ipsem lorem')

def encender():
s.calcel()
t.calcel()

t = perpetualTimer(0.05, apagar)
s = perpetualTimer(5, encender)
t.start()
s.start()

generate this error

Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 1073, in run
self.function(*self.args, **self.kwargs)
File "hilo_infinito_fallo.py", line 15, in handle_function
self.hFunction()
File "hilo_infinito_fallo.py", line 29, in encender
s.calcel()
AttributeError: perpetualTimer instance has no attribute 'calcel'

can you help me?
thank

@TomFaulkner
Copy link
Author

Assuming this is the actual code, you spelled cancel as "calcel."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment