[IPython-dev] Generic gui_thread + IPython: solution already exists!

Prabhu Ramachandran prabhu_r at users.sf.net
Sun Nov 14 14:25:34 EST 2004


Hi,

[Sorry about the cross-posting, but I think this is relevant on both
lists.]

I just happened to read Fernando's post on c.l.py on the way in which
IPython manages to get gtk and wxPython working for matplotlib.  Here
is the thread:

   http://xrl.us/dyej

I then looked at IPython/Shell.py and realized that IPython can
actually be trivially extended to work with *any* wx or gtk app!  

I actually thought of using this approach earlier when I was fixing
gui_thread, but thought IPython would need too many modifications for
this to work.  However, it looks like Fernando has already done all
the work for us.


wxPython
--------

If you just start ipython -pylab you can run the wxPythonDemo
completely interactively from IPython::

    In [1]: cd /usr/local/share/doc/wxPython-2.5.2.8/demo/
    /usr/local/share/doc/wxPython-2.5.2.8/demo
    In [2]: import Main
    In [3]: d = Main.wxPythonDemo(None, 'a')
    In [4]: d.Show(1)
    Out[4]: True
    In [5]: 

This works out nicely!  I also tried a bunch of other tests and things
work well.

Now, obviously, no other application can launch a mainloop.  So we
need to somehow inhibit the user from being able to start it.  The
solution is incredibly simple, replace the real mainloop with a dummy.
Here is a simple example that runs the wxVTKRenderWindowInteractor
example from within IPython!  I've just cut/pasted this from IPython's
history::

    # This is with wxPython-2.5.x; We can do something very similar for
    # wxPython-2.4.x.

    ###########################################
    import wx
    def Dummy_Mainloop(*args, **kw):
        pass
    wx._core_.PyApp_MainLoop = Dummy_Mainloop
    ###########################################

    from vtk.wx import wxVTKRenderWindowInteractor
    wxVTKRenderWindowInteractor.wxVTKRenderWindowInteractorConeExample()
    # Now we see our familiar cone, but the interpreter is still active!
    wxVTKRenderWindowInteractor.wxVTKRenderWindowInteractorConeExample()
    # One more cone!


No, there is no gui_thread in use here!  So, the theory works out in
practice.  Thus with a trivial addition to IPython, almost *ANY*
wxPython app can be made to work perfectly interactively!


GTK
---

If you get the drift of what I did to get wxPython working
interactively for arbitrary apps, you can see where this is headed.
So lets try this approach for gtk.

    In [1]: import gtk 
    In [2]: def f():
       ...:     pass 
       ...:     
    In [3]: gtk.main = f
    In [4]: import menu
    In [5]: m = menu.MenuExample()

    # The example pops up at this point and is fully useable.

    In [6]: gtk.main()
    [...]
    In [8]: menu.main()
    Out[8]: 0

The menu.py example is part of the python-gtk2-tutorial package on
Debian Sarge.  Obviously, the trivial example in the
python-gtk2-tutorial also works just fine.

You don't really need to hijack main, but it helps.  Now, I'm *really*
rusty with pyGTK and I would think you'd need to hijack a few more
functions for this to work perfectly (gtk.mainloop?).  However the
changes are minimal.

Unlike the current gui_thread approach, which takes forever to
startup, the IPython approach is fast since we are only hijacking one
or two functions and not the whole wxPython API!

So I think these additions would make IPython a reliable way to
interactively run most wxPython and GTK apps.

I also vote that once these changes are made, -gthread and -wthread
options be made available.

cheers,
prabhu




More information about the IPython-dev mailing list