[IPython-dev] replacement for appstart_qt4(app) ?

Martin Spacek ipython at mspacek.mm.st
Fri May 20 16:58:57 EDT 2011


Motivated by ipython-qtconsole, I've taken the plunge and switched from 0.10 to 
git master. Apologies if this post is more appropriate for ipython-user.

I have an app that used appstart_qt4(app) in its __name__ == '__main__' block to 
automatically drop into the IPython debugger on any error. This is still 
referenced in:

docs/examples/lib/gui-qt.py

appstart_qt4() is now gone from git master, and I can't seem to find any mention 
of what to use in its place. get_app_qt4() and start_event_loop_qt4() in 
IPython.lib.guisupport seem like good candidates, but AFAICT they don't 
automatically drop you into the ipdb on an error.

I did however find this sys.excepthook method, which seems to work:

http://ipython.scipy.org/doc/manual/html/interactive/reference.html#automatic-invocation-of-pdb-on-exceptions

I want to both allow the user to drop into ipython at any point in time, as well 
as automatically drop into it on any error. After some messing around, I put 
together this minimal working example for git master:


import sys
from PyQt4 import QtCore, QtGui
from IPython import embed
from IPython.core import ultratb

def set_excepthook():
     """Drops us into IPython's debugger on any error"""
     sys.excepthook = ultratb.FormattedTB(mode='Verbose', call_pdb=1)

class SimpleWindow(QtGui.QWidget):
     def __init__(self, parent=None):
         QtGui.QWidget.__init__(self, parent)
         self.setGeometry(300, 300, 300, 200)
         self.setWindowTitle('embed and ipdb test')
         shellButton = QtGui.QPushButton('drop into shell', self)
         shellButton.setGeometry(10, 10, 100, 35)
         self.connect(shellButton, QtCore.SIGNAL('clicked()'),
                      self.shell)
         raiseErrorButton = QtGui.QPushButton('raise Error', self)
         raiseErrorButton.setGeometry(10, 50, 100, 35)
         self.connect(raiseErrorButton, QtCore.SIGNAL('clicked()'),
                      self.raise_error)

     def shell(self):
         embed(display_banner=False) # "self" is accessible from the shell
         # embed() seems to override the excepthook, need to reset it:
         set_excepthook()

     def raise_error(self):
         raise RuntimeError

if __name__ == "__main__":
     # prevents "The event loop is already running" errors:
     QtCore.pyqtRemoveInputHook()
     set_excepthook()
     app = QtGui.QApplication(sys.argv)
     window = SimpleWindow()
     window.show()
     sys.exit(app.exec_())


Hitting the shell button drops you into ipython, and hitting the raise Error 
button drops you into ipdb to inspect the error. I've noticed the embed() call 
clears the sys.excepthook setting, so I have to constantly reset it afterwards. 
Seems a bit messy. Is there a better way to do this?

What I'd ultimately want is a second Qt window running ipython-qtconsole in 
tandem with the main window, so the user never has to hit the "shell" button to 
stop the Qt loop just to inspect all of the existing objects. I used to have 
this kind of functionality in wxPython with pycrust/pyshell. Is such a thing 
currently possible with IPython in Qt?

Cheers,

Martin




More information about the IPython-dev mailing list