[ACCEPTED]-Ctrl-C doesn't work with PyQt-pyqt

Accepted answer
Score: 40

CTRL+C causes a signal to be sent to the 32 process. Python catches the signal, and 31 sets a global variable, something like 30 CTRL_C_PRESSED = True. Then, whenever 29 the Python interpreter gets to execute 28 a new opcode, it sees the variable set 27 and raises a KeybordInterrupt.

This means 26 that CTRL+C works only if the Python interpreter 25 is spinning. If the interpreter is executing 24 an extension module written in C that executes 23 a long-running operation, CTRL+C won't 22 interrupt it, unless it explicitly "cooperates" with 21 Python. Eg: time.sleep() is theoretically 20 a blocking operation, but the implementation 19 of that function "cooperates" with the 18 Python interpreter to make CTRL+C work.

This 17 is all by design: CTRL+C is meant to do 16 a "clean abort"; this is why it gets turned 15 into an exception by Python (so that the 14 cleanups are executed during stack unwind), and 13 its support by extension modules is sort of 12 "opt-in". If you want to totally abort 11 the process, without giving it a chance 10 to cleanup, you can use CTRL+.

When Python 9 calls QApplication::exec() (the C++ function), Qt 8 doesn't know how to "cooperate" with Python 7 for CTRL+C, and this is why it does not work. I 6 don't think there's a good way to "make 5 it work"; you may want to see if you can 4 handle it through a global event filter. — Giovanni 3 Bajo

Adding this to the main program solved 2 the problem.

import signal

signal.signal(signal.SIGINT, signal.SIG_DFL)

I'm not sure what this has to 1 do with the explanation.

Score: 4

I agree with Neil G, and would add this:

If 11 you do not call QApplication.exec_() to start 10 the event loop, and instead execute your 9 program in an interactive python shell (using 8 python -i), then pyqt will automatically 7 process events whenever the interactive 6 prompt is waiting, and Ctrl-C should again 5 behave as expected. This is because the 4 Qt event loop will be sharing time with 3 the python interpreter, rather than running 2 exclusively, allowing the interpreter a 1 chance to catch those interrupts.

More Related questions