[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