[PyQt] Q(Core)Application.exec_() is not interruptable

Giovanni Bajo rasky at develer.com
Thu May 1 20:01:01 BST 2008


On Thu, 2008-05-01 at 20:24 +0200, Christoph Burgmer wrote:
> Am Donnerstag, 1. Mai 2008 schrieb İsmail Dönmez:
> > Following code can't be interrupted with CTRL-C :
> > >>> import sys
> > >>> from PyQt4.QtCore import QCoreApplication
> > >>> QCoreApplication.exec_(sys.argv)
> 
> +1 on the question.
> 
> I tried a lot like using module signal to trap a Ctrl+C but nothing seems to 
> work. I guess the C++ port takes away keyboard events from Python. Any help 
> appreciated.

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
Develer S.r.l.
http://www.develer.com




More information about the PyQt mailing list