我有一个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。
答案 0 :(得分:6)
我知道这已经很晚了,但我确实找到了解决方案。在我的情况下,没有内存泄漏,但一些QObject必须没有正确关闭。 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 )
这对我来说似乎更好。我还将我的应用程序和窗口包含在一个函数中。
答案 1 :(得分:6)
功能包装帮助我
def main():
...
if __name__ == '__main__':
main()