2010-05-12 3 views
1

Я написал небольшое приложение Python, в котором я использую PyGame для отображения простой графики.Обработка KeyboardInterrupt при работе с 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

Что об изменении окончательного цикла к ...:

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

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

+0

Это могло бы работать, если я также делаю то же самое внутри самой нити. Мне кажется немного странным, что я должен явно поймать KeyboardInterrupt. –

+0

@Sebastian, KeyboardInterrupt всегда идет в основной поток, поэтому я не уверен, почему вы также должны поймать его во вторичных потоках. –

+0

Действительно, похоже, что это не похоже на то, что я получил раньше. Возможно, мои файлы не синхронизированы. Благодарю. –

2

Изменив ответ Алекса, обратите внимание, что вы, вероятно, захотите сделать это на всех исключениях, чтобы убедиться, что вы отключили поток, если основной поток не по какой-либо причине, а не только KeyboardInterrupt.

Вам также необходимо переместить обработчик исключений, чтобы избежать условий гонки. Например, может быть KeyboardInterrupt при вызове 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() 

Выполнение этого в итоге делает его более понятным: вы можете сразу сказать, что событие всегда будет установлено независимо от того, как вы выходите из этого кодового блока. (Я предполагаю, что установка события дважды безопасна.)

Если вы не хотите показывать трассировку стека на KeyboardError, вы должны поймать ее и проглотить, но обязательно сделайте это только в своем внешнем коде, чтобы убедитесь, что исключение распространяется полностью.

 Смежные вопросы

  • Нет связанных вопросов^_^