I have a class Controller
with a method job
which I'd like to run at regular intervals using the schedule module. Further, I'd like to have several 'variations' of this job running on separate threads such that they are all can be gracefully interrupted using Cntrl+C. (I do not want to make the threads daemon threads and shut them down abruptly).
Here is what I have so far:
import schedule
import threading
import time
import signal
import sys
class Controller(object):
def __init__(self, name="controller", interval=1):
self.name = name
self.interval = interval
def job(self):
print("My name is {}.".format(self.name))
class ThreadController(threading.Thread):
def __init__(self, *args, **kwargs):
super(ThreadController, self).__init__()
self.controller = Controller(*args, **kwargs)
self._stop = threading.Event()
def stop(self):
self._stop.set()
def stopped(self):
return self._stop.isSet()
def run(self):
schedule.every(self.controller.interval).seconds.do(self.controller.job)
while not self.stopped():
schedule.run_pending()
if __name__ == "__main__":
controller1 = ThreadController(name="foo")
controller2 = ThreadController(name="bar")
try:
controller1.start()
controller2.start()
time.sleep(1000) # This ensures that the execution remains within the 'try' block (for a significant amount of time)
except KeyboardInterrupt:
controller1.stop()
controller2.stop()
The program works, in that for the first 1000 seconds it will alternately print My name is foo.
and My name is bar.
until Cntrl+C is pressed.
To make the code remain within the try
block, however, I am for the time being using time.sleep
which is not an elegant solution. What I actually want is to 'wait' until Cntrl+C is pressed. Is there an elegant way to implement this?
(Another thing I tried is the following, after Capture keyboardinterrupt in Python without try-except:
if __name__ == "__main__":
controller1 = ThreadController(name="foo")
controller2 = ThreadController(name="bar")
def signal_handler(signal, frame):
print("Stopping threads and exiting...")
controller1.stop()
controller2.stop()
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
controller1.start()
controller2.start()
but this seems not to work, as the program keeps printing after Cntrl+C is pressed).