Why doesn't Ctrl+C work to break a Python program that uses PyQt? I want to debug it and get a stack trace and for some reason, this is harder to do than with C++!
-
4You should have used Google ;-) [Your problem explained with solution](http://www.mail-archive.com/pyqt@riverbankcomputing.com/msg13757.html) – user225312 Mar 01 '11 at 21:36
-
@A A - Nice! I thought it was a Ctrl+C versus Ctrl+D situation. – John Giotta Mar 01 '11 at 21:37
-
@Wooble, thanks, I think it's a duplicate. – Neil G Mar 01 '11 at 21:44
2 Answers
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.

- 32,138
- 39
- 156
- 257
-
3I have no idea what this does, but it does work perfectly! EDIT: Read a bit about it [here](https://docs.python.org/3/library/signal.html) so it says, that SIGINT (=Ctrl+C) should do the default action (=quit). – z3ntu Jul 23 '16 at 11:42
I agree with Neil G, and would add this:
If you do not call QApplication.exec_() to start the event loop, and instead execute your program in an interactive python shell (using python -i), then pyqt will automatically process events whenever the interactive prompt is waiting, and Ctrl-C should again behave as expected. This is because the Qt event loop will be sharing time with the python interpreter, rather than running exclusively, allowing the interpreter a chance to catch those interrupts.

- 11,374
- 2
- 48
- 61