Suppose I would like to run a function, called run_forever()
, in a thread, but still have it 'stoppable' by pressing Ctrl+C. I've seen ways of doing this using a StoppableThread
subclass of threading.Thread
, but these seem to involve 'copying' the target function into that subclass. I would like to instead keep the function 'where it is'.
Consider the following example:
import time
import threading
def run_forever(): # An externally defined function which runs indefinitely
while True:
print("Hello, world!")
time.sleep(1)
class StoppableThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self, *args, **kwargs):
super(StoppableThread, self).__init__(*args, **kwargs)
self._stop = threading.Event()
def stop(self):
self._stop.set()
def stopped(self):
return self._stop.isSet()
def run(self):
while not self.stopped():
run_forever() # This doesn't work
# print("Hello, world!") # This does
self._stop.wait(1)
thread = StoppableThread()
thread.start()
time.sleep(5)
thread.stop()
The target function run_forever
is itself a while-loop which never exits. However, to get the desired behavior the wait()
command has to be inside that while-loop, as I understand it.
Is there any way of achieving the desired behavior without modifying the run_forever()
function?
I doubt it's possible.
BTW, have you tried the second solution with
ThreadWithExc
from the post you linked earlier?
It works if the loop is busy pure Python(eg no sleep
), otherwise I'd switch to multiprocessing
and kill subprocess. Here is the code that hopefully exits gracefully(*nix only):
from multiprocessing import Process
from signal import signal, SIGTERM
import time
def on_sigterm(*va):
raise SystemExit
def fun():
signal(SIGTERM, on_sigterm)
try:
for i in xrange(5):
print 'tick', i
time.sleep(1)
finally:
print 'graceful cleanup'
if __name__=='__main__':
proc = Process(target=fun)
proc.start()
time.sleep(2.5)
proc.terminate()
proc.join()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With