I have a python 2.7 application based on PyQt4. I need to process Ctrl+C (KeyboardInterrupt, SIGINT, 2) in specific handler. I see that exception, created by hitting Ctrl+C wasn't caught in try-except block and wasn't seen in handler function, registered by signal library. Ctrl+C just does nothing!
I've tried to do the same without PyQt - signal works good.
Code, used for test doesn't use any PyQt API, so I was able to check with it in both cases.
CTRL+C causes a signal to be sent to the process. Python catches the signal, and sets a global variable, something like CTRL_C_PRESSED = True. Then, whenever the Python interpreter gets to execute a new opcode, it sees the variable set and raises a KeybordInterrupt.
This means that CTRL+C works only if the Python interpreter is spinning. If the interpreter is executing an extension module written in C that executes a long-running operation, CTRL+C won't interrupt it, unless it explicitly "cooperates" with Python. Eg: time.sleep() is theoretically a blocking operation, but the implementation of that function "cooperates" with the Python interpreter to make CTRL+C work.
This is all by design: CTRL+C is meant to do a "clean abort"; this is why it gets turned into an exception by Python (so that the cleanups are executed during stack unwind), and its support by extension modules is sort of "opt-in". If you want to totally abort the process, without giving it a chance to cleanup, you can use CTRL+.
When Python calls QApplication::exec() (the C++ function), Qt doesn't know how to "cooperate" with Python for CTRL+C, and this is why it does not work. I don't think there's a good way to "make it work"; you may want to see if you can handle it through a global event filter. — Giovanni Bajo
Adding this to the main program solved the problem.
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
I'm not sure what this has to do with the explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With