12

KeyboardInterrupts in Idle work for me 90% of the time, but I was wondering why they don't always work. In Idle, if I do

import time
time.sleep(10)

and then attempt a KeyboardInterrupt using Ctrl+C, it does not interrupt the process until after sleeping for 10 seconds.

The same code and a KeyboardInterrupt via Ctrl+C works immediately in the shell.

3
  • Which release of Python? Which platform and operating system? Commented Jul 6, 2011 at 16:56
  • Python 2.7 on Windows XP. Thanks. Commented Jul 6, 2011 at 17:03
  • On my linux system I found that when CTRL+C doesn't work, entering the terminal command kill -2 <PID-of-Idle> will stop Idle. Commented Feb 8, 2014 at 0:55

2 Answers 2

8

A quick glance at the IDLE source reveals that KeyboardInterrupts have some special case handling: http://svn.python.org/view/python/tags/r267/Lib/idlelib/PyShell.py?annotate=88851

On top of that, code is actually executed in a separate process which the main IDLE gui process communicates with via RPC. You're going to get different behavior under that model - it's best to just test with the canonical interpreter (via command line, interactive, etc.)

============

Digging deeper...

The socket on the RPC server is managed in a secondary thread which is supposed to propagate a KeyboardInterrupt using a call to thread.interrupt_main() ( http://svn.python.org/view/python/tags/r267/Lib/idlelib/run.py?annotate=88851 ). Behavior is not as expected there... This posting hints that for some reason, interrupt_main doesn't provide the level of granularity that you would expect: http://bytes.com/topic/python/answers/38386-thread-interrupt_main-doesnt-seem-work

Async API functions in cPython are a little goofy (from my experience) due to how the interpreter loop is handled, so it doesn't surprise me. interrupt_main() calls PyErr_SetInterrupt() to asynchronously notify the interpreter to handle a SIGINT in the main thread. From http://docs.python.org/c-api/exceptions.html#PyErr_SetInterrupt:

This function simulates the effect of a SIGINT signal arriving — the next time PyErr_CheckSignals() is called, KeyboardInterrupt will be raised

That would require the interpreter to go though whatever number of bytecode instructions before PyErr_CheckSignals() is called again - something that probably doesn't happen during a time.sleep(). I would venture to say that's a wart of simulating a SIGINT rather than actually signaling a SIGINT.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 for "test with the canonical interpreter". Especially when dealing with Idle, which has a real tendency to have a lot of magic behaviors. My recommendation to anyone is that if you really want to use Idle is still have a terminal/command window open to do the real testing.
1

See This article:

I quote:

If you try to stop a CPython program using Control-C, the interpreter throws a KeyboardInterrupt exception.

It makes some sense, because the thread is asleep for 10 seconds and so exceptions cannot be thrown until the 10 seconds pass. However, ctrl + c always work in the shell because you are trying to stop a process, not throw a python KeyboardInterrupt exception.

Also, see this previously answered question.

I hope this helps!

3 Comments

So why does the KeyboardInterrupt via Ctrl+C work in the shell but not in Idle?
I don't think I understand what you're saying... what are you saying Ctrl+C does in Idle? Also, Ctrl+C in the shell does result in a KeyboardInterrupt Exception
@ccsndrx: Could it be that, because IDLE is itself a Python program, using time.sleep in IDLE will result in the interpreter not receiving the key event until the sleep period is over, as IDLE has to send the key event to the interpreter itself, while when you use time.sleep from the command-line, it's processed by the interpreter immediately as there's no proxy in between?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.