Python Idle и KeyboardInterrupts - PullRequest
       26

Python Idle и KeyboardInterrupts

11 голосов
/ 06 июля 2011

KeyboardInterrupts in Idle работают для меня 90% времени, но мне было интересно, почему они не всегда работают.В режиме ожидания, если я выполняю

import time
time.sleep(10)

, а затем пытаюсь выполнить KeyboardInterrupt с помощью Ctrl + C, он не прерывает процесс до тех пор, пока не перестанет спать в течение 10 секунд.

Тот же код и KeyboardInterruptчерез Ctrl + C работает сразу в оболочке.

Ответы [ 2 ]

8 голосов
/ 06 июля 2011

Быстрый взгляд на источник 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.

1 голос
/ 06 июля 2011

См. статья :

Цитирую:

Если вы пытаетесь остановить программу CPython используя Control-C, интерпретатор генерирует исключение KeyboardInterrupt.

Это имеет некоторый смысл, потому что нить спит в течение 10 секунд, и поэтому исключения не могут быть выброшены, пока не пройдет 10 секунд. Однако ctrl + c всегда работает в оболочке, потому что вы пытаетесь остановить процесс, а не вызывать исключение Python KeyboardInterrupt.

Также смотрите этот ранее ответ вопрос .

Надеюсь, это поможет!

...