5

我有一个 PySide 应用程序,它在 QWidget 中托管一个 VLC MediaPlayer 实例。当应用程序通过 QMainWindow 的关闭事件或使用 QApplication.quit() 关闭时,UI 消失,然后我得到一个 Windows 对话框“python.exe 已停止工作”。

QApplication 托管一个自定义 QMainWindow 类,其中包含一个自定义 QWidget(它处理所有 UI 任务,QMainWindow 处理线程之间的消息传递 - 应用程序记录击键并在后台线程中写入输出文件)。还有一个运行主 QWidget 的计时器,它使用视频中的当前位置更新 LineEdit。

无论文件是否被写入(代码被注释掉),都会发生崩溃。

我是否需要执行某种类型的垃圾收集,或者可能以特定顺序处理我的对象?我尝试停止计时器,将 MediaPlayer、Instance 和承载 MediaPlayer 的帧全部设置为 None,然后销毁帧 (self.videoFrame.destroy()),但应用程序仍然崩溃。

基本代码基于 vlc 的 repo示例中的示例 Qt 应用程序,它没有特殊的垃圾收集或对象处理。

我在 Windows XP 上运行 Python 2.6。现在我直接从命令行运行 Python,但是一旦我修复了这个崩溃,就将它设置为使用 Py2Exe 创建一个 exe。

4

2 回答 2

7

我知道这已经晚了,但我确实找到了解决方案。就我而言,没有内存泄漏,但某些 QObjects 一定没有正确关闭。Python 3,PySide 1.2.1

class CustomWindow(QtGui.QMainWindow):
    def cleanUp(self):
        # Clean up everything
        for i in self.__dict__:
            item = self.__dict__[i]
            clean(item)
     # end cleanUp
# end class CustomWindow

def clean(item):
    """Clean up the memory by closing and deleting the item if possible."""
    if isinstance(item, list) or isinstance(item, dict):
        for _ in range(len(item)):
            clean(list(item).pop())
    else:
        try:
            item.close()
        except (RuntimeError, AttributeError): # deleted or no close method
            pass
        try:
            item.deleteLater()
        except (RuntimeError, AttributeError): # deleted or no deleteLater method
            pass
# end clean

if __name__ == "__main__":
    app = Qtgui.QApplication(sys.argv)

    window = CustomWindow()
    window.show()

    app.aboutToQuit.connect(window.cleanUp)

    sys.exit(app.exec_())

这将遍历主窗口中的所有内容,如果可能,它将关闭并删除所有找到的项目。它使我的应用程序立即关闭,没有内存泄漏或问题。您可能还必须专门关闭某些项目,并确保尝试删除已删除的项目不会导致错误。

编辑

我最终用一个名为QtGui.qApp.closeAllWindows(). 不过,后来这个问题又来了。我现在认为这与 C++ 和 python 对象不同步以及如何清理对象有关。

class CloseAllFilter(QtCore.QObject):
    """Event filter for closing all windows if the widget is closed."""
    def eventFilter(self, receiver, event):
        results = super().eventFilter(receiver, event)
        if event.type() == QtCore.QEvent.Close and event.isAccepted():
            for win in QtGui.qApp.topLevelWidgets():
                if win != receiver:
                    try:
                        win.close()
                        # win.deleteLater() # This seemed to make python crash more consistently.
                    except (AttributeError, RuntimeError):
                        pass
        return results
# end class CloseAllFilter

window.__close_all_filter = CloseAllFilter()
window.installEventFilter(window.__close_all_filter )

这似乎对我更有效。我还将我的应用程序和窗口包装在一个函数中。

于 2014-02-06T21:20:57.777 回答
6

包装功能帮助了我

def main():
    ...

if __name__ == '__main__':
    main()
于 2015-02-09T12:37:57.033 回答