Windows - select.select, timeout and KeyboardInterrupt

Thomas Heller theller at ctypes.org
Thu May 6 15:58:15 EDT 2010


Paul Moore schrieb:
>>From a quick experiment, it seems that select.select with a timeout
> doesn't react to a keyboard interrupt until the timeout expires.
> Specifically, if I do
> 
> s = socket.socket()
> select.select([s], [], [], 30)
> 
> and then press Ctrl-C, Python waits for the 30 seconds before raising
> KeyboardInterrupt.
> 
> Is this a known limitation on Windows? I see no mention of it in the
> documentation. Assuming it is a known limitation, is there a way round
> it? (I'm writing a tiny server using asyncore/asynchat, and the
> delayed response to Ctrl-C is a mild nuisance. Solutions such as "use
> twisted", while probably the sensible option in a wider context, don't
> really apply here - I need something within the confines of the stdlib
> if it's to be worth doing).

If you look at the source code for time.sleep(), which CAN be interrupted
by pressing Ctrl-C, you will find that it is carefully programmed to be
interruptible (sp?).  Which is not the case for select.select(), obviously.

I guess the best way might be to split your select.select() call into several
ones, using a smaller timeout like 1 second for example.

BTW: I have experimented with calling the win32 function SetConsoleCtrlHandler()
before the call to select.select().  This allows to install a python callback 
function which is called when Ctrl+C is pressed.  However it seems this callback
is not able to interrupt the select() call - but it can 'raise SystemExit()'
which will terminate the script.  Here is the code:

"""
import ctypes, select, socket

@ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_uint)
def HandlerRoutine(dwCtrlType):
    print "hoppla", dwCtrlType
    if dwCtrlType == 0: # CTRL+C
        raise SystemExit()
    return 1

s = socket.socket()

print "Waiting."
ctypes.windll.kernel32.SetConsoleCtrlHandler(HandlerRoutine, 1)
select.select([s], [], [], 30)
ctypes.windll.kernel32.SetConsoleCtrlHandler(HandlerRoutine, 0)
print "Done."
"""




More information about the Python-list mailing list