Ctrl-C/SIGTERM/SIGINT seem to be ignored by tkinter. Normally it can be captured again with a callback. This doesn't seem to be working, so I thought I'd run tkinter in another thread since its mainloop() is an infinite loop and blocks. I actually also want to do this to read from stdin in a separate thread. Even after this, Ctrl-C is still not processed until I close the window. Here's my MWE:
#! /usr/bin/env python
import Tkinter as tk
import threading
import signal
import sys
class MyTkApp(threading.Thread):
def run(self):
self.root = tk.Tk()
self.root.mainloop()
app = MyTkApp()
app.start()
def signal_handler(signal, frame):
sys.stderr.write("Exiting...\n")
# think only one of these is needed, not sure
app.root.destroy()
app.root.quit()
signal.signal(signal.SIGINT, signal_handler)
Results:
What's going on here and how can I make Ctrl-C from the terminal close the app?
Update: Adding a poll, as suggested, works in the main thread but does not help when started in another thread...
class MyTkApp(threading.Thread):
def poll(self):
sys.stderr.write("poll\n")
self.root.after(50, self.poll)
def run(self):
self.root = tk.Tk()
self.root.after(50, self.poll)
self.root.mainloop()
Since your tkinter app is running in another thread, you do not need to set up the signal handler in the main thread and just use the following code block after the app.start()
statement:
import time
while app.is_alive():
try:
time.sleep(0.5)
except KeyboardInterrupt:
app.root.destroy()
break
You can then use Ctrl-C to raise the KeyboardInterrupt
exception to close the tkinter app and break the while loop. The while loop will also be terminated if you close your tkinter app.
Note that the above code is working only in Python 2 (as you use Tkinter
in your code).