Обработка KeyboardInterrupt при работе с PyGame - PullRequest
2 голосов
/ 12 мая 2010

Я написал небольшое приложение на 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 закрывается, приложение закрывается; если приложение завершает свою задачу, приложение закрывается.

Проблема в том, что если я Ctrl - C в консоли Python, приложение выдает KeyboardInterrupt, но продолжает работать.

Поэтому возникает вопрос: что я сделал неправильно в цикле обновления и как мне его исправить, чтобы KeyboardInterrupt заставил приложение завершить работу?

Ответы [ 2 ]

3 голосов
/ 12 мая 2010

Как насчет изменения вашего последнего цикла на ...:

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

Т.е. убедитесь, что вы перехватываете прерывания клавиатуры и обрабатываете их так же, как событие выхода.

2 голосов
/ 12 мая 2010

Изменяя ответ Алекса, обратите внимание, что вы, вероятно, хотите сделать это для всех исключений, чтобы обеспечить отключение потока в случае сбоя основного потока по любой причине, а не только по 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, вы должны перехватить ее и проглотить, но убедитесь, что делаете это только в самом внешнем коде, чтобы исключение распространялось полностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...