关闭并退出时崩溃
Posted
技术标签:
【中文标题】关闭并退出时崩溃【英文标题】:Crash on close and quit 【发布时间】:2013-09-11 04:49:29 【问题描述】:我有一个 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 example 的示例 Qt 应用程序,它没有特殊的垃圾收集或对象处理。
我在 Windows XP 上运行 Python 2.6。现在我直接从命令行运行 Python,但是一旦我修复了这个崩溃,就设置它使用 Py2Exe 创建一个 exe。
【问题讨论】:
使用 PyQt 或 PySide 或两者都会发生这种情况吗? PySide 在对象生命周期方面存在一些已知问题。 PySide,我还没试过 PyQt。我用 PyQt 标记了这个问题,因为这些库非常相似。即使我打开应用程序、启动视频并立即关闭应用程序,也会发生这种情况。 那我建议用 PyQt 试试,只是为了排除 PySide 错误导致问题的可能性。 【参考方案1】:我知道这已经晚了,但我确实找到了解决方案。就我而言,没有内存泄漏,但某些 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 )
这似乎对我更有效。我还将我的应用程序和窗口包装在一个函数中。
【讨论】:
感谢您的意见。我确实最终在我更熟悉的 .Net 中重写了这个,并且真的没有时间回去与旧代码集成,所以我无法标记这是否是回答。如果我回到它,我会看看这是否能解决问题。 我试过并得到了这个: Traceback(最近一次调用最后):文件“C:...gui.py”,第 175 行,在包装功能帮助了我
def main():
...
if __name__ == '__main__':
main()
【讨论】:
谢谢,您的回答对我有帮助,但您能解释一下原因吗?以上是关于关闭并退出时崩溃的主要内容,如果未能解决你的问题,请参考以下文章
使用自定义 IDocHostUIHandler 和关闭窗口时崩溃
当系统清除内存并关闭 UIViewController 时,iOS 崩溃