出现不稳定的“无效信号签名” PySide QWebPage 中的错误

发布于 2024-12-27 01:43:18 字数 1423 浏览 9 评论 0原文

我正在创建一个使用 PySide 自动加载网页和创建屏幕截图的应用程序(不,我不能使用现有的解决方案之一)。应用程序的一部分获取 URL 列表,并使用 new QWebPage 对象依次加载每个 URL。页面加载后,将截取屏幕截图并删除 QWebPage 对象。

时不时地,如果运行次数足够多,我会从 PySide 收到以下错误,作为 RuntimeError 异常:

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

第一行打印到 STDERR(可能是 Qt?),第二行是 Python 异常。

loadStarted() 是一个内置的 QWebPage 信号,不是我创建的。这在 90% 的情况下都有效,而且我不明白是什么导致它偶尔失败。

老实说,这个应用程序在设计上相当不寻常,因为它将 PySide/Qt 挂接到 uWSGI 服务的 Web 应用程序中 - 这意味着,例如,我没有使用 QApplication 事件循环,而是为每个页面加载使用本地事件循环。我对 Qt 或 Python 也没有经验,所以我可能犯了很多错误,但我不知道这些错误是什么。

我想这篇文章可能与此有关,但我不确定。

关于下一步去哪里有什么建议吗?

更新:信号通过以下代码连接:

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 对象被创建为不同的单个 QObject 实例的子级,该实例在进程关闭之前不会被删除。一旦我完成了它们,就会通过调用 page.deleteLater() 来删除它们。由于我正在运行本地事件循环,因此我通过调用以下命令在退出本地事件循环后触发延迟删除:

 # 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)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

掩耳倾听 2025-01-03 01:43:18

我遇到了同样的问题(我每隔一段时间就会收到这些错误,但我无法始终如一地重现它)。我认为你可能是对的,当你尝试将信号连接到它们时,它与不存在的方法有关 - 只是为了测试这一点,我将 .connect 调用放在一个单独的方法中,并且错误消失了。例如:

编辑:
(几个小时后)我想我说得太早了 - 我刚刚又收到了错误。

更新:
(几周后)

我经常使用语法,有时甚至会遇到运行时错误(可能是 PySide 中的这个错误?)。我仍然不完全确定为什么,但由于错误发生的不一致,您可能可以安全地像这样强制它:

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

如果您真的想要安全,您可以保留一个循环计数器并如果信号在某个阈值之前未正确连接,则使程序崩溃。

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.

若相惜即相离 2025-01-03 01:43:18

无论如何,在我升级到 PySide 1.2.1 后,这个问题和其他问题终于得到了很好的解决。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文