有什么好的做法可以避免在PyQt中崩溃或挂起? - python

我同时喜欢python和Qt,但是对我来说很明显Qt并不是在设计时就考虑到python的。有很多方法可以使PyQt / PySide应用程序崩溃,即使使用适当的工具,也很难调试很多方法。

我想知道:使用PyQt和PySide时避免崩溃和锁定的良好实践是什么?从常规的编程技巧和支持模块到高度特定的解决方法和应避免的错误,这些都可以。

参考方案

通用编程实践

  • 如果必须使用多线程代码,则永远不要从非GUI线程访问GUI。总是通过发出信号或其他线程安全机制将消息发送到GUI线程。
  • 在使用“模型/查看任何内容”时要小心。 TableView,TreeView等。它们很难正确编程,并且任何错误都会导致无法跟踪的崩溃。使用Model Test帮助确保模型内部一致。
  • 了解Qt对象管理与Python对象管理交互的方式以及可能出错的情况。参见http://python-camelot.s3.amazonaws.com/gpl/release/pyqt/doc/advanced/development.html
  • 没有父级的Qt对象由Python“拥有”;只有Python可以删除它们。
  • 带有父级的Qt对象是Qt的“所有者”,如果删除了它们的父级,则Qt将删除它们。
  • 示例:Core dump with PyQt4
  • QObject通常不应引用其父代或其任何祖先(可以使用弱引用)。这将最多导致内存泄漏,并偶尔导致崩溃。
  • 注意Qt自动删除对象的情况。如果未通知python包装器删除了C++对象,则对其进行访问将导致崩溃。由于PyQt和PySide在跟踪Qt对象方面遇到困难,因此可以通过许多不同的方式发生这种情况。
  • 复合控件,例如QScrollArea及其滚动条,QSpinBox及其QLineEdit等。(Pyside没有此问题)
  • 删除QObject会是automatically delete all of its children(但是PyQt通常可以正确处理此问题)。
  • 从QTreeWidget中删除项目将导致所有关联的小部件(使用QTreeWidget.setItemWidget设置)被删除。
    # Example:
    from PyQt4 import QtGui, QtCore
    app = QtGui.QApplication([])
    
    # Create a QScrollArea, get a reference to one of its scroll bars.
    w = QtGui.QWidget()
    sa = QtGui.QScrollArea(w)
    sb = sa.horizontalScrollBar()
    
    # Later on, we delete the top-level widget because it was removed from the 
    # GUI and is no longer needed
    del w
    
    # At this point, Qt has automatically deleted all three widgets.
    # PyQt knows that the QScrollArea is gone and will raise an exception if
    # you try to access it:
    sa.parent()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    RuntimeError: underlying C/C++ object has been deleted
    
    # However, PyQt does not know that the scroll bar has also been deleted.
    # Since any attempt to access the deleted object will probably cause a 
    # crash, this object is 'toxic'; remove all references to it to avoid 
    # any accidents
    sb.parent()
    # Segmentation fault (core dumped)
    
  • 具体的解决方法/错误

  • 在不先调用prepareGeometryChange()的情况下更改QGraphicsItems的边界可能会导致崩溃。
  • 在QGraphicsItem.paint()中引发异常会导致崩溃。始终在paint()中捕获异常并显示一条消息,而不是让异常继续进行。
  • QGraphicsItems永远不要保留对其生活的QGraphicsView的引用。(弱引用是可以的)。
  • 重复使用QTimer.singleShot会导致锁定。
  • 避免将QGraphicsView与QGLWidget一起使用。
  • 避免出口崩溃的实践

    不属于QGraphicsScene的

  • QGraphicsItems可能导致退出时崩溃。
  • 引用其父级或任何祖先的

  • QObject可能导致退出崩溃。
  • 没有父级的

  • QGraphicsScene可能导致退出崩溃。
  • 避免出口崩溃的最简单方法是在python开始收集Qt对象之前调用os._exit()。但是,这可能很危险,因为程序的某些部分可能依赖于正确的退出处理才能正确运行(例如,终止日志文件或正确关闭设备句柄)。至少,应该在调用os._exit()之前手动调用atexit回调。
  • Python GPU资源利用 - python

    我有一个Python脚本在某些深度学习模型上运行推理。有什么办法可以找出GPU资源的利用率水平?例如,使用着色器,float16乘法器等。我似乎在网上找不到太多有关这些GPU资源的文档。谢谢! 参考方案 您可以尝试在像Renderdoc这样的GPU分析器中运行pyxthon应用程序。它将分析您的跑步情况。您将能够获得有关已使用资源,已用缓冲区,不同渲染状态上…

    Python:图像处理可产生皱纹纸效果 - python

    也许很难描述我的问题。我正在寻找Python中的算法,以在带有某些文本的白色图像上创建皱纹纸效果。我的第一个尝试是在带有文字的图像上添加一些真实的皱纹纸图像(具有透明度)。看起来不错,但副作用是文本没有真正起皱。所以我正在寻找更好的解决方案,有什么想法吗?谢谢 参考方案 除了使用透明性之外,假设您有两张相同尺寸的图像,一张在皱纹纸上明亮,一张在白色背景上有深…

    Python uuid4,如何限制唯一字符的长度 - python

    在Python中,我正在使用uuid4()方法创建唯一的字符集。但是我找不到将其限制为10或8个字符的方法。有什么办法吗?uuid4()ffc69c1b-9d87-4c19-8dac-c09ca857e3fc谢谢。 参考方案 尝试:x = uuid4() str(x)[:8] 输出:"ffc69c1b" Is there a way to…

    Python sqlite3数据库已锁定 - python

    我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…

    Python:如何停止多线程的numpy? - python

    我知道这似乎是一个荒谬的问题,但是我必须在与部门中其他人共享的计算服务器上定期运行作业,当我开始10个作业时,我真的希望它只占用10个核心而不是更多;我不在乎每次运行一个内核所需的时间是否更长:我只是不想让它侵犯其他人的领土,这将需要我放弃工作等等。我只想拥有10个核心,仅此而已。更具体地说,我在基于Python 2.7.3和numpy 1.6.1的Redh…