PyQt事件循环和ipython中的异常

2024-10-03 06:24:15 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个PyQt程序,它显示一些小部件和按钮。在

我希望该程序要么作为独立的python实例运行,要么在ipython环境中运行。在本例中,我在Jupyter控制台中使用以下魔术命令(以前在启动ipythonqtconsole时必须使用--gui=qt)

%pylab qt

为了使程序同时工作,我的主模块有以下几行:

^{pr2}$

这是我的问题:事件循环生成的异常很难被用户检测到,因为它们会在后台控制台中弹出。我想捕捉事件循环中发生的任何异常,并显示一个警告(在QMainWindow状态栏中显示警告,以使用户知道发生了异常)。在

我尝试了几种策略,但PyQt和Ipython的内部机制似乎有一个阴谋,使之不可能实现:

  • 重新实施系统异常挂钩(请参见Preventing PyQt to silence exceptions occurring in slots):由于ipython不断重写,所以不起作用系统异常挂钩在
  • 检测IPython是否正在运行,然后使用IPYTHON.set_自定义_exc(Opening an IPython shell on any (uncatched) exception):不幸的是,qt事件循环异常不会触发处理程序。在
  • 覆盖QApplication.notify.通知:倒霉,本地人QApplication.notify.通知我打算在派生函数中调用的函数不会引发异常,返回值(布尔值)也不会反映插槽的正确执行。这个线程中的答案很有趣:How to log uncatched exceptions of a QApplication?,然而,这个策略似乎在qtc++中有效,但是notify的python包装器只是将异常打印到控制台,而不是引发异常。在

这是一个长期困扰我的问题。有人有办法吗?在


Tags: to用户程序警告系统ipython事件notify
1条回答
网友
1楼 · 发布于 2024-10-03 06:24:15

实际上,开发人员的回答给我指明了正确的方向: 问题是每次执行ipython单元时,新的系统异常挂钩一旦执行完毕系统异常挂钩返回到上一个(请参见ipkernel/kernelapp.py). 在

因此,改变系统异常挂钩在正常的ipython单元指令中,不会更改qt事件循环期间执行的excepthook。在

一个简单的解决方案是使用monkeypatch系统异常挂钩qt事件内部:

from PyQt4 import QtCore, QtGui
import sys
from traceback import format_exception

def new_except_hook(etype, evalue, tb):
    QtGui.QMessageBox.information(None, 
                                  str('error'),
                                  ''.join(format_exception(etype, evalue, tb)))

def patch_excepthook():
    sys.excepthook = new_except_hook
TIMER = QtCore.QTimer()
TIMER.setSingleShot(True)
TIMER.timeout.connect(patch_excepthook)
TIMER.start()

这个方法的一个优点是,它同样适用于独立执行和ipython执行。在

我想我们也可以想象一下,根据触发异常的小部件,在每个小部件的事件处理程序内调用patch_exceptinthook,来修补不同版本的新的“除了”钩子。在

相关问题 更多 >