Python - get key pressing ?

Duncan Booth duncan at NOSPAMrcp.co.uk
Thu Jul 3 11:07:22 EDT 2003


Peter Hansen <peter at engcorp.com> wrote in
news:3F043A1F.81E6CA6 at engcorp.com: 

> Krisztian Kepes wrote:
>> 
>> I want to create an py program what process datas for long time.
>> But: I want to abort it if I need.
>> Not with Ctrl+Break !
> 
> Why not?  Ctrl+Break, or more typically Ctrl-C, is the de facto
> standard approach for terminating a console (non-GUI) application.
> 
>> If I push a key (B, or other), the script must stop his work, and
>> save the result created before.
> 
> In this case, just wrap the code with a "try/except KeyboardInterrupt"
> and put your "stop and save" code in the except block.  (Note that
> Ctrl-Break will bypass this, but Ctrl-C is caught as you would
> expect.) 

Assuming we are talking about the Windows platform here.
If you want to catch Ctrl-Break as well (and have a resonably recent 
version of Python), you just need to do this:

    import signal
    signal.signal(signal.SIGBREAK, signal.default_int_handler)

and now pressing Ctrl-Break throws KeyboardInterrupt (in your application's 
main thread only).

Of course the problem with handling the KeyboardInterrupt exception is that 
your data might not be in a suitable state for saving when the exception is 
thrown. Also (at least on Windows) it doesn't interrupt a socket call, so 
if you are using sockets you have to wait for a timeout. What I prefer to 
do is to start the main processing in a background, daemon thread. The main 
thread then just waits (by calling sleep for a short time) for the 
KeyboardInterrupt. When the interrupt is raised you can then try to 
communicate with the background thread in a more orderly fashion, either by 
sending it a message or by using a Lock() around access to the data you 
want to save.

Here's an example of what I mean. The code below runs an XMLRPC server 
under windows but control break allows the system to shut down properly, 
closing files etc. This code didn't have locking around the XMLRPC 
requests, it should have because then the main thread could make sure it 
didn't shut down mid request, but it wasn't a big issue here.

def RunXMLRPCServer():
    """Run the XMLRPCServer, but do so in a different thread.
    The main thread simply sleeps so that it can respond to Ctrl+Break
    """
    def XMLRPCThread():
        server = SimpleXMLRPCServer.SimpleXMLRPCServer(('127.0.0.1', 8888))
        server.register_instance(MyXMLServer())
        server.serve_forever()

    import threading
    th = threading.Thread(target=XMLRPCThread)
    th.setDaemon(1)
    th.start()
    # Make ctrl+break raise a KeyboardInterrupt exception.
    signal.signal(signal.SIGBREAK, signal.default_int_handler)
    try:
        while 1:
            time.sleep(0.1)
    except KeyboardInterrupt:
        log.info("Break pressed.")


-- 
Duncan Booth                                             duncan at rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?




More information about the Python-list mailing list