【问题标题】:Handling KeyboardInterrupt when working with PyGame使用 PyGame 时处理 KeyboardInterrupt
【发布时间】:2010-05-12 14:51:37
【问题描述】:

我编写了一个小型 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 导致应用程序终止?

【问题讨论】:

    标签: python pygame


    【解决方案1】:

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

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

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

    【讨论】:

    • 这似乎可行,只要我在线程本身内部也这样做。不过,我必须明确地捕获 KeyboardInterrupt,这对我来说似乎有点奇怪。
    • @Sebastian,KeyboardInterrupt 总是转到主线程,所以我不知道你为什么还要在辅助线程中捕获它。
    • 确实如此,似乎无法复制我之前得到的东西。也许我的文件不同步。谢谢。
    【解决方案2】:

    修改 Alex 的回答,注意您可能希望在 all 异常情况下执行此操作,以确保在主线程因任何原因而失败时关闭线程,而不仅仅是 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()
    

    在 finally 中执行此操作会更清楚:您可以立即知道无论您如何退出此代码块,事件都将始终设置。 (我假设两次设置事件是无害的。)

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      相关资源
      最近更新 更多