Почему я не могу обработать прерывание клавиатуры в python?

Я пишу код python 2.6.6 на windows, который выглядит так:

try:
    dostuff()
except KeyboardInterrupt:
    print "Interrupted!"
except:
    print "Some other exception?"
finally:
    print "cleaning up...."
    print "done."

dostuff() - это функция, которая зацикливается до бесконечности, читая по строке за раз из входного потока и действуя на них. Я хочу иметь возможность остановить ее и очистить, когда я нажимаю ctrl-c.

Вместо этого происходит то, что код под except KeyboardInterrupt: вообще не выполняется. Единственное, что выводится, это "cleaning cleaning up...", а затем выводится отслеживание, которое выглядит так:

Traceback (most recent call last):
  File "filename.py", line 119, in <module>
    print 'cleaning up...'
KeyboardInterrupt

Итак, код обработки исключений НЕ выполняется, а отслеживание утверждает, что прерывание клавиатуры произошло во время пункта finally, что не имеет смысла, потому что нажатие клавиши ctrl-c - это то, что вызвало выполнение этой части в первую очередь! Даже общий пункт except: не выполняется.

EDIT: Основываясь на комментариях, я заменил содержимое блока try: на sys.stdin.read(). Проблема по-прежнему возникает точно так, как описано, с первой строкой блока finally:, который выполняется, а затем печатает тот же traceback.

EDIT #2:. Если я добавляю практически все, что угодно, после чтения, обработчик работает. Итак, это не работает:

try:
    sys.stdin.read()
except KeyboardInterrupt:
    ...

Но это работает:

try:
    sys.stdin.read()
    print "Done reading."
except KeyboardInterrupt:
    ...

Вот что выводится:

Done reading. Interrupted!
cleaning up...
done.

Итак, по какой-то причине выводится строка "Done reading.", хотя исключение произошло в предыдущей строке. На самом деле это не проблема - очевидно, я должен уметь обрабатывать исключение в любом месте внутри блока "try". Однако, печать не работает нормально - она не печатает новую строку после нее, как это должно быть! Прерывание" печатается в той же строке... с пробелом перед ним, по какой-то причине...? В любом случае, после этого код делает то, что должен.

Мне кажется, что это ошибка в обработке прерывания во время заблокированного системного вызова.

38
задан Josh 5 January 2011 в 18:45
поделиться