Why is my python QObject's slot not triggered by emit()

528 views Asked by At

I have python filesystem (watchdog) code successfully triggering a pyqtSignal#emit() call from its own thread (proven by a pdb trace).

This signal should be wired via connect(...) to a corresponding @pyqtSlot function on my own QObject, but the target function is in fact never called when a filesystem change triggers the emit.

The example code can be inspected at https://github.com/cefn/xmlorgmode/blob/2b97ff9994132def035d325fc7f7095c9fe187f2/index.py

and can be invoked as follows, with an XML file and an XQuery file passed in from the same folder.

python index.py index.xml index.xq

This loads perfectly the first time, but no refresh ever takes place as triggered by the filesystem, which is what I would expect if my code worked. Failure is silent.

Can anyone suggest the additional event loop structures which I need for the watchdog-triggered emit to correspond to a call to QueryDisplay#update(...) ?

BACKGROUND

I've been experimenting with passing dynamically constructed HTML to QWebView backed by text files in a folder which change occasionally. Because of the requirement that QWebView#setHtml(...) is called within its own thread, I've had to try and figure out signals and slots, and I've hit a brick wall. The threading arrangement that I've arrived at is somehow broken but I can't figure out how.

I cannot establish how my QObject is supposed to be associated with an event loop within the appropriate thread so that things emitted can get handled. Having debugged the running code, the QApplication, QWebView and my QObject all share the same thread when calling #thread() interactively with pdb to establish affinity, just before entering the app.exec_() loop. I thought this would mean that all eventing for all these objects would be handled within app.exec_() but I must have misunderstood the model somehow.

(Pdb) adaptor.thread()
<PyQt4.QtCore.QThread object at 0xb30c3c44>
(Pdb) display.view.thread()
<PyQt4.QtCore.QThread object at 0xb30c3c44>
(Pdb) app.thread()
<PyQt4.QtCore.QThread object at 0xb30c3c44>
1

There are 1 answers

0
cefn On

This was PEBKAC, but with at least two interesting feature interactions. Essentially the emit() was indeed triggering the slot but all the attempts I'd made to monitor the triggering were flawed.

First of all, PDB simply ignores breakpoints if they don't occur in the main thread. They are never triggered, even if those lines of code are actually executed, if it happens in another thread. This is extremely bad news, but worse, is a silent failure. A workaround is to manually change the code to invoke PDB inline, rather than use the debugger shell, but that kind of defeats the purpose of having a debugger to investigate the flow of control. For this reason I didn't see the invocation actually happening even with a breakpoint in place.

Secondly, QXMLQuery silently ignores changes to files and caches automatically, so even if it's reinvoked, and the underlying 'focus' files have actually changed, it ignores the changes. For this reason I couldn't see the results of the interaction being triggered (a cache prevented the change appearing).