- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
tl;dr -- 在 PySide 应用程序中,即使所有其他引用都已删除,其方法抛出异常的对象仍将保持事件状态。为什么?如果有的话,人们应该怎么做?
在使用带有 PySide GUI 的模型- View -呈现器架构构建简单的 CRUDish 应用程序的过程中,我发现了一些奇怪的行为。就我而言:
weakref.ref
) 以避免循环pypubsub
消息传递库间接通信,但这也仅存储对听众的弱引用,并且不是下面 MCVE 的一个因素。)但是,方法抛出异常的 Presenter 并没有像预期的那样被删除。该应用程序继续运行,因为 PySide 使用了 some magic捕捉异常。有问题的 Presenter 继续接收和响应绑定(bind)到它的任何 View 事件。但是当 View 被删除时,抛出异常的 Presenter 仍然存在,直到整个应用程序关闭。 MCVE ( link for readability ):
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, **kwargs)
self.logger = logging.getLogger('OuterView')
# Menus
menu_bar = self.menuBar()
test_menu = menu_bar.addMenu('&Test')
self.open_action = QtGui.QAction('&Open inner', self, triggered=self.on_open, enabled=True)
test_menu.addAction(self.open_action)
self.close_action = QtGui.QAction('&Close inner', self, triggered=self.on_close, enabled=False)
test_menu.addAction(self.close_action)
def closeEvent(self, event, *args, **kwargs):
self.logger.debug('Exiting application')
event.accept()
def on_open(self):
self.setCentralWidget(InnerView(self))
self.open_action.setEnabled(False)
self.close_action.setEnabled(True)
def on_close(self):
self.setCentralWidget(None)
self.open_action.setEnabled(True)
self.close_action.setEnabled(False)
class InnerView(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(InnerView, self).__init__(*args, **kwargs)
self.logger = logging.getLogger('InnerView')
self.logger.debug('Initializing InnerView (id:%s)' % id(self))
self.presenter = InnerPresenter(self)
# Layout
layout = QtGui.QHBoxLayout(self)
alert_button = QtGui.QPushButton('Alert!', self, clicked=self.presenter.on_alert)
layout.addWidget(alert_button)
raise_button = QtGui.QPushButton('Raise exception!', self, clicked=self.presenter.on_raise_exception)
layout.addWidget(raise_button)
self.setLayout(layout)
def __del__(self):
super(InnerView, self).__del__()
self.logger.debug('Deleting InnerView (id:%s)' % id(self))
def show_alert(self):
QtGui.QMessageBox(text='Here is an alert').exec_()
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG)
app = QtGui.QApplication(sys.argv)
view = OuterView()
view.show()
sys.exit(app.exec_())
打开和关闭内部 View ,您会看到 View 和演示者都按预期删除了。打开内 View ,点击按钮在presenter上触发异常,然后关闭内 View 。 View 将被删除,但在应用程序退出之前演示者不会。
为什么? 据推测,代表 PySide 捕获所有异常的任何东西都存储了对抛出它的对象的引用。为什么需要这样做?
我应该如何继续(当然,除了编写永远不会导致异常的代码之外)?我有足够的理由不依赖 __del__
进行资源管理。我知道我无权期望在捕获但未真正处理的异常之后发生任何事情,但这让我觉得不必要地丑陋。一般来说,我应该如何处理这个问题?
最佳答案
问题是 sys.last_tracback
和 sys.last_value
。
当以交互方式引发回溯时,这似乎是被模拟的,最后一个异常及其回溯分别存储在 sys.last_value
和 sys.last_traceback
中.
做
del sys.last_value
del sys.last_traceback
# for consistency, see
# https://docs.python.org/3/library/sys.html#sys.last_type
del sys.last_type
将释放内存。
值得注意的是最多一个异常和回溯对可以被缓存。这意味着,因为您是理智的并且不依赖 del
,所以不会造成大量损失。
但是如果你想回收内存,只需删除那些值即可。
关于python - 为什么 PySide 的异常处理会延长这个对象的生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26086365/
我想更新小部件的值,但为了防止无限循环,我需要防止调用此小部件的回调函数 .valueChanged信号。 以下示例完全按预期工作: Qt = PySide class MainWindow(Acto
使用以下代码,在尝试发出信号时出现错误(“PySide.QtCore.Signal”对象没有属性“emit”): #!/usr/bin/env python from PySide import Qt
我是 Python 新手。我同时安装了 Python 2.7 和 Python 3。我刚刚尝试通过 Homebrew 安装 PySide 并收到此消息: PySide package successf
是否可以使用 PySide 中的 Web 类之一加载包含按钮的本地 html/JS 文件,并将这些按钮连接到 PySide 插槽? 最佳答案 您可以使用 QtWebKit 将 QObject 导出到
我一直在寻找一个工作示例,该示例如何在使用 QT 设计器创建的 pyside 中嵌入 matplotlib 图,同时将逻辑保存在单独的文件中。我知道网上有很多例子,但没有一个真正使用 QT 设计器,然
我想我可以通过将\PySide 文件夹附加到我的环境的“搜索路径”来添加 PySide 库,但智能感知似乎没有发现任何东西。不过,它正在使用我的其他图书馆。有什么建议吗? 注意:我已经安装了 PTVS
我正在设计一个 Pyside Qt 应用程序,我想切换 QtCore.Qt.WindowStaysOnTopHint我的主窗口中的窗口标志。使用此代码设置此提示工作正常: self.setWindow
你如何在 PySide 中禁用声子? 我正在尝试使用 QWebpage 并且我不希望 phonon 启动,因为我正在编写的应用程序是服务器端应用程序,并且不需要媒体。我尝试了一些东西,但没有找到任何真
本文为大家分享了pyside pyqt实现鼠标右键菜单功能的具体代码,供大家参考,具体内容如下 在三维软件中使用pyside/pyqt编写gui界面时,为了艺术家使用操作的简洁,以及方便,经常会使
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我试图在 PySide 的单独线程中运行一个长任务,以便主线程可以继续处理 GUI 事件。我已经阅读了执行此操作的正确方法: 将任务封装在 QObject 子类中,其中工作在 run() 方法中完成,
我想知道如何根据最大标签的最大宽度/高度截断QLabel中的文本。 输入的文本可以是任意长度,但是为了保持整洁的布局,我想截断长字符串以填充最大空间(小部件的最大宽度/高度)。 例如。: 'A ve
我有一个界面,屏幕顶部有 4 个按钮,下面有 QFrame。我想根据按下的按钮更改 QFrame 中的布局。例如,如果按下 Button_1 显示一个 TextEdit Widget,如果按下 But
我想制作一个小部件的角。在 PyQt 中,我用样式表解决了这个问题,效果很好。我想在 PySide 中做同样的事情,但由于某些原因它不起作用。 这是我的代码: TitelWidget = QtGui.
我是 python 和 pyside 的新手。我将尝试成功运行以下代码。但现在我希望程序在显示窗口后等待用户无法使用它的定义时间,然后升级状态栏。我会尝试 sleep() 但不知道它必须以正确的方式放
我从 example of Zetcode 开始学习 PySide并尝试编写具有两个窗口的应用程序:“布局 View ”的父级“示意图 View ”,每个窗口都有菜单栏。启动时应该只是原理图窗口,布局
我从 example of Zetcode 开始学习 PySide并尝试编写具有两个窗口的应用程序:“布局 View ”的父级“示意图 View ”,每个窗口都有菜单栏。启动时应该只是原理图窗口,布局
我正在尝试通过 pyside 设置 QGridLayout 小部件的背景图像(位于与应用程序相同的文件夹中),但无济于事我已经查看了有关样式表的所有图、文档和论坛帖子,但仍然我不知道我做错了什么。 f
我有一个带有 5 个按钮的布局,我充当“菜单”,因此您单击一个按钮,会显示一个 View ,单击另一个按钮,会显示另一个 View 。我需要找出单击了哪个按钮,以便我可以根据按下的按钮执行某些操作。类
基本上我想要的是: 在主窗口中显示一个小部件,其中包含打开 QFileDialog 的按钮 选择文件后,包含按钮的小部件应切换到新的小部件,该新小部件会显示一些基于文件内容的可视化效果。 在下面的代码
我是一名优秀的程序员,十分优秀!