I'm trying this simple thread with a while loop inside. When I'm inside the while loop, Ctrl C has no effect in stopping my program. Once I go do something else after the while loop, the script stops as intended. What can I do so my script can be gracefully killed both while being in the while loop and after? (Edit: This seems to be a problem exclusive to Windows, iOS and Ubuntu seem to do what I want)
import time, threading
class MainClass(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
while True:
time.sleep(1)
print("Looping")
# Script entry point
if __name__ == '__main__':
a = MainClass()
a.daemon = True
a.start()
a.join()
CodePudding user response:
This is a known issue, explained in Issue 35935.
A way to solve it is to use an event, which is passed into the thread class, which waits for the SIGINT to be triggered. As I understand, a way to overcome the fact that the main thread is blocking the event signal is to revert to the default kernel behaviour of SIGINT using signal.signal(signal.SIGINT, signal.SIG_DFL)
, (solution pointed out by the issue OP), and the meaning of SIG_DFL is explained f.e. here. As to why this has to be the case is beyond the scope of my knowledge.
This is by no means a perfect solution, but works on Windows using Python 3.8 .
Implementation:
import time, threading
import signal
class MainClass(threading.Thread):
def __init__(self,event):
super().__init__()
self.event = event
def run(self):
while not event.is_set():
time.sleep(1)
print("Looping")
# Script entry point
if __name__ == '__main__':
try:
event = threading.Event()
a = MainClass(event)
a.daemon=True
a.start()
signal.signal(signal.SIGINT, signal.SIG_DFL)
event.wait()
except KeyboardInterrupt:
event.set()
sys.exit(1)