Handling KeyboardInterrupt when working with PyGame
I wrote a small Python application where I am using PyGame to display some simple graphics.
I have a somewhat simple PyGame loop going through the base of my application, for example:
stopEvent = Event()
# Just imagine that this eventually sets the stopEvent
# as soon as the program is finished with its task.
disp = SortDisplay(algorithm, stopEvent)
def update():
""" Update loop; updates the screen every few seconds. """
while True:
stopEvent.wait(options.delay)
disp.update()
if stopEvent.isSet():
break
disp.step()
t = Thread(target=update)
t.start()
while not stopEvent.isSet():
for event in pygame.event.get():
if event.type == pygame.QUIT:
stopEvent.set()
It works great and is great for normal program termination; if the PyGame window is closed, the application is closed; if the application completes its task, the application is closed.
I have a problem: if I Ctrl- Cin the Python console, application issues KeyboardInterrupt
, but continues to run.
So the question is, what did I do wrong in my update loop and how do I fix it to KeyboardInterrupt
force the application to terminate?
a source to share
Modifying Alex's answer, note that you probably want to do this on all exceptions to make sure you disconnect the thread if the main thread fails for some reason, not just KeyboardInterrupt.
You also need to move your exception handler to avoid race conditions. For example, there might be KeyboardInterrupt when calling stopEvent.isSet ().
try:
t = Thread(target=update)
t.start()
while not stopEvent.isSet():
for event in pygame.event.get():
if event.type == pygame.QUIT:
stopEvent.set()
finally:
stopEvent.set()
Doing that eventually makes it clearer: you can tell right away that the event will always be set no matter how you exit that block of code. (I am assuming setting the event is twice safe.)
If you don't want to show the stack trace on KeyboardError, you must catch it and internalize it, but be sure to only do this in your outer code to make sure the exception is propagated completely.
a source to share