Быстрый взгляд на источник IDLE показывает, что KeyboardInterrupts имеет некоторую особую обработку: http://svn.python.org/view/python/tags/r267/Lib/idlelib/PyShell.py?annotate=88851
Кроме того, код фактически выполняется в отдельном процессе, с которым основной процесс графического интерфейса IDLE взаимодействует черезRPC.В этой модели вы получите другое поведение - лучше всего протестировать с помощью канонического интерпретатора (через командную строку, интерактивно и т. Д.)
===========
Копать глубже ...
Сокет на сервере RPC управляется во вторичном потоке, который должен распространять KeyboardInterrupt с помощью вызова thread.interrupt_main () (http://svn.python.org/view/python/tags/r267/Lib/idlelib/run.py?annotate=88851)Поведение там не такое, как ожидалось ... Эта публикация намекает на то, что по какой-то причине interrupt_main не обеспечивает ожидаемого уровня детализации: http://bytes.com/topic/python/answers/38386-thread-interrupt_main-doesnt-seem-work
Асинхронные API-функции в cPython немного глупы (из моего опыта) из-за того, как обрабатывается цикл интерпретатора, поэтому меня это не удивляет.interrupt_main () вызывает PyErr_SetInterrupt () для асинхронного уведомления интерпретатора для обработки SIGINT в основном потоке.С http://docs.python.org/c-api/exceptions.html#PyErr_SetInterrupt:
Эта функция имитирует эффект прихода сигнала SIGINT - при следующем вызове PyErr_CheckSignals () будет сгенерировано KeyboardInterrupt
Для этого потребуетсяинтерпретатор, чтобы идти через любое количество инструкций байт-кода до того, как PyErr_CheckSignals () будет вызван снова - то, что, вероятно, не происходит во время time.sleep ().Рискну сказать, что это имитация SIGINT, а не сигнал SIGINT.