【问题标题】:How can I profile events in a PyQt application?如何分析 PyQt 应用程序中的事件?
【发布时间】:2020-05-16 13:38:15
【问题描述】:

这个stack overflow answer 似乎提供了一种非常干净的方法来监控 C++ 中所有 Qt 事件的持续时间。我有兴趣在 Python 中为 PyQt5 应用程序做类似的事情。

高级目标是进行分析,我们可以选择启用以获得使应用程序感觉缓慢的硬数字。油漆花了多长时间?鼠标点击需要多长时间?有什么想法吗?

【问题讨论】:

    标签: pyqt pyqt5 profiling timing


    【解决方案1】:

    您可以将链接答案中的 C++ 代码 python 化:

    from PyQt5.QtCore import QElapsedTimer
    from PyQt5.QtWidgets import QApplication, QPushButton
    
    class MyApplication(QApplication):
    
        t = QElapsedTimer()
    
        def notify(self, receiver, event):
            self.t.start()
            ret = QApplication.notify(self, receiver, event)
            if(self.t.elapsed() > 10):
                print(f"processing event type {event.type()} for object {receiver.objectName()} " 
                      f"took {self.t.elapsed()}ms")
            return ret
    
    
    if __name__ == "__main__":
        app = MyApplication([])
        ....
        app.exec()
    

    【讨论】:

    • 哇,好用。我是 PyQT 的新手,我没有在源代码中看到“通知”。我不确定您是否可以覆盖这样的随机 C++ 方法。效果很好,谢谢!
    • 你是说QApplication的来源吗? notify() 是 QObject 的一个方法,所以你不会在 QApplication 的源代码中找到它。 PyQt5 的 API 非常接近于 Qt 的 C++ 版本。如此之多,以至于当我需要查找 PyQt5 的内容时,我几乎总是使用 Qt 的官方文档。
    • 我没有在所有 QtPy5 源代码中看到 notify() 方法。我现在收集虽然 PyQt5 公开了 C++ 类/方法,但这并不意味着它包含它们的 Python 版本。这是有道理的。无论如何,这很好用。
    【解决方案2】:

    重用相同的QElapsedTimer 实例是个坏主意,因为notify 可能在方法本身内部被调用。在这种情况下,start 将再次被调用,这会导致不正确的较短时间测量。另外,如果您使用线程,我希望这会导致问题。为了避免所有这些,我将使用局部变量并使用time.monotonic 而不是QElapsedTimer 来测量时间差。

    当我尝试在notify() 之后调用receiver.objectName() 时,我偶尔会遇到异常。 Qt 抱怨receiver 已被删除。

    这对我有用:

    import time
    from PyQt5.QtWidgets import QApplication, QPushButton
    
    class MyApplication(QApplication):
    
        def notify(self, receiver, event):
            eventType = event.type()
            receiverName = receiver.objectName()
            start = time.monotonic()
            ret = QApplication.notify(self, receiver, event)
            end = time.montonic()
            elapsedMSec = (end - start) * 1000
            if(elapsedMSec > 10):
                print(f"processing event type {eventType} for object {receiverName} took {elapsedMSec} msec")
            return ret
    
    
    if __name__ == "__main__":
        app = MyApplication([])
        ....
        app.exec()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-06
      • 1970-01-01
      • 2016-08-25
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多