Getting erratic "Invalid Signal signature" errors in PySide QWebPage

945 views Asked by At

I am creating an application which automates loading webpages and creating screenshots (no, I cannot use one of the existing solutions) using PySide. One part of the app gets a list of URLs and loads each URL in turn using a new QWebPage object. After the page is loaded a screenshot is taken and the QWebPage object is deleted.

Every now and then, given enough runs, I get the following error from PySide, as a RuntimeError exception:

Invalid Signal signature: loadStarted()
Failed to connect signal loadStarted().

The first line is printed to STDERR (probably by Qt?) and the second line is the Python exception.

loadStarted() is a built-in QWebPage signal, not something I created. This works 90% of the time, and I could not figure out what makes it fail occasionally.

To be honest, this app is quite unusual in design, as it hooks PySide/Qt into a uWSGI served web app - this means that for example I am not using the QApplication event loop but rather a local event loop for each page load. I am also not experienced in either Qt or Python so it's possible I'm making a lot of mistakes, but I can't figure out what those are.

I am thinking this post might have something to do with it, but I'm not sure.

Any suggestions on where to look next?

UPDATE: the signal is connected through the following code:

class MyWebPage(QWebPage):

    def __init__(self, parent=None):
        super(MyWebPage, self).__init__(parent)
        self.loadStarted.connect(self.started)
        self.loadFinished[bool].connect(self.finished)

MyWebPage objects are created as children of a different single QObject instance which is not deleted until the process shuts down. They are deleted by calling page.deleteLater() once I am done with them. Since I am running a local event loop, I trigger deferred deletions to happen after exiting local event loop by calling:

 # self.eventLoop is the local event loop, which at this stage is not running
 self.eventLoop.processEvents()

 # self.app is the QApplication instance
 self.app.sendPostedEvents(None, QEvent.DeferredDelete)
2

There are 2 answers

0
shevron On BEST ANSWER

For what its worth, this and other issues were finally solved in a decent way after I upgraded to PySide 1.2.1.

0
accidental_PhD On

I was having the same problem (I'd get these errors every once in a while, but I couldn't consistently reproduce it). I think you may be right that it has something to do with methods not existing when you try to connect the signals to them - just to test that, I put the .connect calls in a separate method, and the errors went away. For example:

EDIT: (a few hours later) I guess I spoke too soon - I just got the error again.

UPDATE: (a few weeks later)

I played around with the syntax a lot and occasionally even got a RuntimeError (possibly this bug in PySide?). I'm still not completely sure why, but as the error happens inconsistently, you're probably safe in forcing it like this:

class MyWebPage(QWebPage):

def __init__(self, parent=None):
    super(MyWebPage, self).__init__(parent)

    success = False
    while not success:
        try:
            success = self.loadStarted.connect(self.started)
        except RuntimeError:
            success = False

    success = False
    while not success:
        try:
            success = self.loadFinished[bool].connect(self.finished)
        except RuntimeError:
            success = False

If you really want to be safe, you could maybe keep a loop counter and just crash the program if the signal doesn't connect correctly before some threshold.