Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ctrl-C doesn't work with PyQt [duplicate]

Tags:

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++!

like image 368
Neil G Avatar asked Mar 01 '11 21:03

Neil G


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.

like image 117
Neil G Avatar answered Oct 13 '22 19:10

Neil G


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.

like image 23
Luke Avatar answered Oct 13 '22 19:10

Luke