小编gra*_*irt的帖子

为什么PySide的异常处理延长了这个对象的生命周期?

tl; dr - 在PySide应用程序中,即使已删除所有其他引用,其方法抛出异常的对象仍将保持活动状态.为什么?什么,如果有的话,应该做些什么呢?

在使用带有PySide GUI的Model-View-Presenter架构构建简单CRUDish应用程序的过程中,我发现了一些奇怪的行为.就我而言:

  • 界面分为多个视图 - 即,显示数据不同方面的每个标签页可能是其自己的View类
  • 视图首先被实例化,并且在初始化时,它们实例化它们自己的Presenter,保持对它的正常引用
  • Presenter接收对View it驱动器的引用,但将其存储为弱引用(weakref.ref)以避免循环
  • 没有其他对Presenter的强引用.(演示者可以间接与pypubsub消息传递库进行通信,但这也仅存储对侦听器的弱引用,并且不是下面MCVE中的一个因素.)
  • 因此,在正常操作中,当删除视图时(例如,当关闭选项卡时),随后其引用计数变为0时删除其Presenter

但是,方法抛出异常的Presenter不会按预期删除.应用程序继续运行,因为PySide使用一些魔法来捕获异常.有问题的演示者继续接收并响应与其绑定的任何View事件.但是当删除视图时,抛出异常的Presenter将保持活动状态,直到整个应用程序关闭.MCVE(可读性链接):

import logging
import sys
import weakref

from PySide import QtGui


class InnerPresenter:
    def __init__(self, view):
        self._view = weakref.ref(view)
        self.logger = logging.getLogger('InnerPresenter')
        self.logger.debug('Initializing InnerPresenter (id:%s)' % id(self))

    def __del__(self):
        self.logger.debug('Deleting InnerPresenter (id:%s)' % id(self))

    @property
    def view(self):
        return self._view()

    def on_alert(self):
        self.view.show_alert()

    def on_raise_exception(self):
        raise Exception('From InnerPresenter (id:%s)' % id(self))


class OuterView(QtGui.QMainWindow):
    def __init__(self, *args, **kwargs):
        super(OuterView, self).__init__(*args, …
Run Code Online (Sandbox Code Playgroud)

python garbage-collection exception-handling pyside

6
推荐指数
1
解决办法
437
查看次数