0

I've seen Launch an IPython shell on exception, but that doesn't help me here (testing on Python 2.7.1, Ubuntu 11.04). Consider the following example:

import wx

class Tester(object):
  def __init__(self, innum):
    print("innum: " +str(innum))
    for x in xrange(innum,-1,-1):
      tval = float(innum)/x
      print(tval)

class MyFrame(wx.Frame):
  def __init__(self, parent):
    wx.Frame.__init__(self, parent, -1, "Except Test")
    self.btn = wx.Button(self, -1, "Click me")
    self.btn.SetBackgroundColour(wx.NamedColour("orange"))
    psizer = wx.BoxSizer(wx.HORIZONTAL)
    psizer.Add(self.btn, 1, wx.EXPAND | wx.ALL, 20)
    self.SetSizer(psizer)
    self.SetSize((200,200))
    self.btn.Bind(wx.EVT_BUTTON, self.runTest)
    self.Layout()
  def runTest(self, event):
    t = Tester(3)
    print(t)

if __name__ == '__main__':
  runWx = True# False#
  if not(runWx):
    t = Tester(3)
    print(t)
  else:
    app = wx.App(0)
    frame = MyFrame(None)
    app.SetTopWindow(frame)
    frame.Show()
    app.MainLoop()

If I set the runWx to False, so the program runs strictly from the command line, all is as expected:

$ python -m pdb test.py 
> /tmp/test.py(1)<module>()
-> import wx
(Pdb) c
innum: 3
1.0
1.5
3.0
Traceback (most recent call last):
  File "/usr/lib/python2.7/pdb.py", line 1314, in main
    pdb._runscript(mainpyfile)
  File "/usr/lib/python2.7/pdb.py", line 1233, in _runscript
    self.run(statement)
  File "/usr/lib/python2.7/bdb.py", line 387, in run
    exec cmd in globals, locals
  File "<string>", line 1, in <module>
  File "test.py", line 1, in <module>
    import wx
  File "test.py", line 7, in __init__
    tval = float(innum)/x
ZeroDivisionError: float division by zero
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /tmp/test.py(7)__init__()
-> tval = float(innum)/x
(Pdb) p x
0
(Pdb) q
Post mortem debugger finished. The test.py will be restarted
> /tmp/test.py(1)<module>()
-> import wx
(Pdb) q

... that is, when the exception is raised, pdb raises a post mortem shell, I can inspect values, and exit the program.

But if runWx is True, as in the code, then I have to click the button on the GUI to raise an exception; and in that case, I get this:

$ python -m pdb test.py 
> /tmp/test.py(1)<module>()
-> import wx
(Pdb) c
innum: 3
1.0
1.5
3.0
Traceback (most recent call last):
  File "test.py", line 22, in runTest
    t = Tester(3)
  File "test.py", line 7, in __init__
    tval = float(innum)/x
ZeroDivisionError: float division by zero

... that is - no pdb shell is shown, instead the output terminal is simply blocking after printing the traceback (and in fact, you can click the button repeatedly, and repeatedly have the traceback printed in the terminal, while never dropping to the pdb shell).

Is it possible to drop to a pdb shell upon an unhandled exception raised from a wx (or any) GUI event - and if so, how do I do it in the example above?

Community
  • 1
  • 1
sdaau
  • 36,975
  • 46
  • 198
  • 278

1 Answers1

0

I believe all you have to do is import pdb and set a trace in your event handler:

def runTest(self, event):
    import pdb
    pdb.set_trace()
    t = Tester(3)
    print(t)

That worked for me on Xubuntu 14.04 with wxPython 2.8.12 and Python 2.7. See also:

Community
  • 1
  • 1
Mike Driscoll
  • 32,629
  • 8
  • 45
  • 88