使用PyGame时处理KeyboardInterrupt

时间:2010-05-12 14:51:37

标签: python pygame

我编写了一个小型Python应用程序,我使用PyGame来显示一些简单的图形。

我在我的应用程序的基础上有一个简单的PyGame循环,如下所示:

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()

对于正常的程序终止,它一切正常和花花公子;如果PyGame窗口关闭,应用程序关闭;如果应用程序完成其任务,则应用程序将关闭。

我遇到的麻烦是,如果我在Python控制台中 Ctrl - C ,应用程序会抛出KeyboardInterrupt,但会继续运行。

因此问题是:在我的更新循环中我做错了什么,如何纠正它以便KeyboardInterrupt导致应用程序终止?

2 个答案:

答案 0 :(得分:3)

如何将最终循环更改为......:

while not stopEvent.isSet():
    try:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                stopEvent.set()
    except KeyboardInterrupt:
        stopEvent.set()

即,确保捕获键盘中断并将它们视为退出事件。

答案 1 :(得分:2)

修改Alex的回答,请注意您可能希望在所有异常上执行此操作,以确保在主线程因任何原因失败时关闭线程,而不仅仅是KeyboardInterrupt。

您还需要移出异常处理程序,以避免竞争条件。例如,调用stopEvent.isSet()时可能会有KeyboardInterrupt。

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()

最后这样做会更清楚:无论你如何退出这个代码块,都可以立即告诉事件将始终设置。 (我假设将事件设置两次是无害的。)

如果您不想在KeyboardError上显示堆栈跟踪,则应该捕获它并吞下它,但请确保仅在最外层的代码中执行此操作,以确保异常完全传播出去。