【问题标题】:Exceptions in PyQt event loop and ipythonPyQt 事件循环和 ipython 中的异常
【发布时间】:2017-03-29 06:18:39
【问题描述】:

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

我希望程序作为独立的 python 实例运行,或者在 ipython 环境中运行。在这种情况下,我在 Jupyter 控制台中使用了以下魔法命令(以前我在启动 ipython qtconsole 时必须使用 --gui=qt)

%pylab qt

为了有一个双向运行的程序,我的主模块有以下几行:

APP = QtGui.Qapplication.instance() # retrieves the ipython qt application if any
if APP is None:
    APP = QtGui.QApplication(["foo"]) # create one if standalone execution

if __name__=='__main__':
    APP.exec_() # Launch the event loop here in standalone mode 

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

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

这是一个困扰我很久的问题。有人有解决办法吗?

【问题讨论】:

  • 尝试this answer中建议的解决方案。
  • 我忘记了这一点:覆盖 IPython 将用作 sys.excepthook 的猴子补丁的函数(如您的回答中所建议的那样)也不起作用。事实上,带有 qt 选项的 Ipython 甚至会阻止 qt 事件循环调用 sys.excepthook。我不明白 IPython 开发人员在捕获事件循环异常时发现了什么如此淫秽?!
  • 老实说,我认为在这里报告所有这些是浪费时间:您需要与 ipython 开发人员一起讨论。
  • 谢谢,我在 ipython 的 github issue 页面发帖:github.com/ipython/ipython/issues/10057。与此同时,我也注意到了这个相关的问题。 stackoverflow.com/questions/26426419/….

标签: python qt ipython pyqt4 qtconsole


【解决方案1】:

实际上,开发人员的回答为我指明了正确的方向: 问题是每次执行 ipython 单元时,都会对新的 sys.excepthook 进行猴子补丁,一旦执行完成,sys.excepthook 就会恢复到前一个(参见 ipkernel/kernelapp.py)。

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

一个简单的解决方案是在 qt 事件中对 sys.excepthook 进行monkeypatch:

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 执行。

我想人们也可以想象通过在每个小部件的 event_handler 中调用 patch_excepthook 来修改不同版本的 new_except_hook,具体取决于触发异常的小部件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-20
    相关资源
    最近更新 更多