[Idle-dev] Re: [Tutor] How to interrupt in IDLE (fwd)

Guido van Rossum guido@python.org
Mon, 15 Apr 2002 08:53:53 -0400


> >Thanks.  Unfortunately, there's no real easy way out of this.
> >The ^C can only be detected by Tkinter's event loop, and that isn't
> >active when the Python VM is executing code, only when it's asking for
> >input or printing output.
> 
> I think that there is one easy way out of this, but really the Tkinter
> mainloop C code should be fixed to get around the 30 msec. sleep in the
> Tkinter mainloop. The sleep in the loop creates dead time,

Only 30 msec, which is plenty for responding to keyboard and mouse input.

> causes CPU burn
> because it isn't using some kind of select call,

Not measurably; during those 30 msec it's not using CPU time, and the
test it does for an event is fast.  I bet you can't notice the CPU
usage at all.

> and won't process Python
> signals if it's vwait waiting in Tk.

Which is *not* the problem here.  The problem is that when you've got
some kind of window (X11 or Win32 or Mac, doesn't matter), ^C doesn't
send a signal, but simply a keyboard character.

 I have advocated scheduling something
> regularly on the Tcl event queue to check for Python signals, using a
> function already in _tkinter.c - Tkapp_CreateTimerHandler.

Yeah, but unfortunately nobody has been able to come up with working
code -- and the only person in the world who might be able to (Jeff
Hobbs) was lukewarm the last time this was brought up.
(Understandably since he'd be helping the "competition". :-)

> Although I think this is technically the correct way to do it, there is an
> easy route that may solve your problem: do the mainloop in Python. 
> 
>         self.exit = -1
>         while self.exit < 0:
>             self.tk.dooneevent(0)
> 
> where self.tk.quit() is changed to set self.exit to 0. This has no sleep,
> no dead time, reacts to Keyboard Interupt after any Tcl event (e.g. mouse
> move),

I think you misunderstand the situation completely.  The ^C doesn't
get translated into a KeyboardInterrupt by self.tk.dooneevent() --
there's code in IDLE to do that -- and, in addition, the original
problem was that when the user code is executing

    while 1:
        pass

there's nothing looking for Tk events at all.

>and has the added advantage of being able to easily add hooks into
> the main loop to poll for other things:
> 
>         self.exit = -1
>         while self.exit < 0:
>            self.tk.dooneevent(0)
>            # plug in any other polling checks here: asyncore ...
>            if self.hooks is not None: map (eval, self.hooks)
> 
> This seems to work well, though I haven't tested it using threads. 
> To see examples of this approach, I think the CVS version of the Tix demos 
> have been switched over to use this:
> http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/python/
> python/dist/src/Demo/tix/samples/SHList2.py?
> rev=1.3&content-type=text/vnd.viewcvs-markup

--Guido van Rossum (home page: http://www.python.org/~guido/)