Interrupting the keyboard in a program waiting for an event

The following program hangs on the terminal in such a way that it ignores Ctrl+C

. This is quite annoying as I have to restart the terminal every time one of the threads hangs.

Is there a way to catch KeyboardInterrupt

while waiting for an event?

import threading
def main():
    finished_event = threading.Event()
    startThread(finished_event)
    finished_event.wait()#I want to stop the program here
    print('done!')
def startThread(evt):
    """Start a thread that will trigger evt when it is done"""
    #evt.set()
if __name__ == '__main__':
    main()

      

+3


source to share


3 answers


Update: As of current Python 3 is finished_event.wait()

running on my Ubuntu machine (since Python 3.2). You don't need to supply a parameter timeout

in order to interrupt it with Ctrl+C. You need to pass a parameter timeout

to CPython 2.

Here's a complete sample code:

#!/usr/bin/env python3
import threading

def f(event):
    while True:
        pass
    # never reached, otherwise event.set() would be here

event = threading.Event()
threading.Thread(target=f, args=[event], daemon=True).start()
try:
    print('Press Ctrl+C to exit')
    event.wait()
except KeyboardInterrupt:
    print('got Ctrl+C')

      

Maybe bugs , associated with the Ctrl + the C . Check if it works in your environment.




Old poll answer:

You can try to allow the interpreter to start the main thread:

while not finished_event.wait(.1): # timeout in seconds
    pass

      

If you just want to wait for the child thread to execute:

while thread.is_alive():
    thread.join(.1)

      

+1


source


If you want to avoid polling, you can use pause()

the signal module function instead finished_event.wait()

. signal.pause()

is a blocking function and is unblocked when a signal is received by a process. In this case, when the ^ C key is pressed, the SIGINT signal will unlock the function. Please note that this feature does not work on Windows according to the documentation. I tried this on Linux and it worked for me.



I found this solution on this SO thread .

+3


source


You can also fix the Event.wait () function like this:

def InterruptableEvent():
    e = threading.Event()

    def patched_wait():
        while not e.is_set():
            e._wait(3)

    e._wait = e.wait
    e.wait = patched_wait
    return e


>>> event = InterruptableEvent()
>>> try:
...     event.wait()
... except KeyboardInterrupt:
...     print "Received KeyboardInterrupt"
... 
^CReceived KeyboardInterrupt

      

This works because wait () with a timeout argument calls KeyboardInterrupt.

0


source







All Articles