[IPython-dev] Detecting GUI mainloop running in IPython

Brian Granger ellisonbg at gmail.com
Sun Jul 25 17:22:42 EDT 2010

On Sun, Jul 25, 2010 at 1:35 PM, Eric Firing <efiring at hawaii.edu> wrote:

> On 07/25/2010 09:10 AM, Brian Granger wrote:
> > Gael,
> >
> > Great questions.  The short answer is that the traditional methods of
> > discovering if the event loop is running won't work.  This issue will
> > become even more complicated with we implement GUI integration in the
> > new 2 process frontend/kernel.  We still need to decide how we are going
> > to handle this.  Here was the last email we sent out a long time ago
> > that didn't really get any response:
> Brian,
> I've been looking at that old message for a couple of weeks, trying to
> figure out how to respond from the mpl perspective.  I'm still quite
> uncertain, and I would be pleased to see people with a better
> understanding of gui toolkits, event loops, and ipython step in.

Part of the challenge is that Fernando and I (who have done the GUI work in
IPython) don't know GUI toolkits very well.

> Preliminary thoughts:
> Although ipython has provided invaluable service to mpl by enabling
> interactive plotting for all gui backends, I am not at all sure that
> this functionality should be left to ipython in the long run.  The
> problem is that mpl is used in a variety of ways and environments.  Gui
> functionality is central to mpl; it seems odd, and unnecessarily
> complicated, to have to delegate part of that to an environment, or
> shell, like ipython.

The challenge is that other projects (traits, mayavi, chaco, etc.) need
these capabilities as well.  They either need to be in IPython or a separate

At present, for most backends, interactive mpl plotting is possible in
> ipython without any of ipython's gui logic.  That is, running vanilla
> ipython one can:
> In [1]: from pylab import *
> In [2]: ion()
> In [3]: plot([1,2,3])
> Out[3]: [<matplotlib.lines.Line2D object at 0x3f3c350>]
> and the plot appears with full interaction, courtesy of the
> PyOS_InputHook mechanism used by default in tk, gtk, and qt4.  If mpl
> simply adopted the new ipython code to add this capability to wx, then
> wx* backends would be included.  The advantage over leaving this in
> ipython is that it would give mpl more uniform behavior regardless of
> whether it is run in ipython or elsewhere.

Yes, tk, gtk and qt4 already use the input hook mechanism and it doesn't
require IPython in any way.  At some level all the 0.11 IPython GUI support
does is implement a PyOS_InputHook for wx and then provide a single
interface for managing any GUI toolkit.  Maybe this code will eventually
make its way into wx, but even then, it makes sense to have a single nice
interface for this.

> Sometimes one wants mpl's show() to have blocking behavior.  At present
> it blocks when mpl is not in interactive mode.  The blocking is
> implemented by starting the gui event loop.
> One very useful service ipython provides is enabling mpl scripts with
> show() to be run in non-blocking mode.  I think this would be even
> better if one could easily choose whether to respect the interactive
> setting.  Then, one could either run a script in ipython exactly as it
> would be run from the command line--that is, blocking at each show() if
> not in interactive mode--or one could run it as at present in pylab
> mode.  I think this could be done with simple modifications of the pylab
> mode code.

> I have no idea how all this will be affected by the proposed two-process
> model for ipython.
The two process model will not use the inputhook stuff at all.  It will
simple start a full GUI eventloop in the kernel process.  Because it is a
very different approach than the inputhook approach we will need to think
carefully about what interface we provide to projects like mpl.

> >
> > Current situation
> > =============
> >
> > Both matplotlib and ets have code that tries to:
> >
> > * See what GUI toolkit is being used
> > * Get the global App object if it already exists, if not create it.
> > * See if the main loop is running, if not possibly start it.
> >
> > All of this logic makes many assumptions about how IPython affects the
> > answers to these questions.  Because IPython's GUI support has changed
> > in significant
> > ways, current matplotlib and ets make incorrect decisions about these
> > issues (such as trying to
> > start the event loop a second time, creating a second main App ojbect,
> > etc.) under IPython
> > 0.11.  This leads to crashes...
> This complexity is the reason why I would like to delegate all gui
> control back to mpl.
We can't really do that.  The issue is that people want to use both mpl and
traits and chaco in the same code.  If mpl is completely responsible for the
GUI stuff, how will traits and chaco configure their GUI stuff.  The usual
approach of seeing if there is a global app, and using it won't always work.
 In the event loop is running using PyOS_InputHook, how will
mpl/chaco/traits tell if the event loop is running?

> >
> > Description of GUI support in 0.11
> > ==========================
> >
> > IPython allows GUI event loops to be run in an interactive IPython
> session.
> > This is done using Python's PyOS_InputHook hook which Python calls
> > when the :func:`raw_input` function is called and is waiting for user
> input.
> > IPython has versions of this hook for wx, pyqt4 and pygtk.  When the
> > inputhook
> > is called, it iterates the GUI event loop until a user starts to type
> > again.  When the user stops typing, the event loop iterates again.  This
> > is how tk works.
> >
> > When a GUI program is used interactively within IPython, the event loop
> of
> > the GUI should *not* be started. This is because, the PyOS_Inputhook
> itself
> > is responsible for iterating the GUI event loop.
> >
> > IPython has facilities for installing the needed input hook for each GUI
> > toolkit and for creating the needed main GUI application object. Usually,
> > these main application objects should be created only once and for some
> > GUI toolkits, special options have to be passed to the application object
> > to enable it to function properly in IPython.
> I don't know anything about these options.  I think that presently, mpl
> is always making the app object--but it is hard to keep all this
> straight in my head.
Not quite.  When mpl is run in pylab mode in IPython, IPython always creates
the App object.  It the monkey patches the App creation methods to return
the existing version.  Thus, while it looks like mpl is creating the App
objects, it isn't.  This type of monkey patching doesn't play well with the
inputhook stuff.

> >
> > What we need to decide
> > ===================
> >
> > We need to answer the following questions:
> >
> > * Who is responsible for creating the main GUI application object,
> IPython
> >   or third parties (matplotlib, enthought.traits, etc.)?
> >
> At least for mpl, mpl always needs to be *able* to make it, since it
> can't depend on being run in ipython.  Therefore it seems simpler if mpl
> always *does* make it.
This logic has to be conditional.  mpl will have to first look somewhere???
to see if someone else (IPython, traits, chaco) has created it and if the
event loop is running.  This is the trick.

> > * What is the proper way for third party code to detect if a GUI
> application
> >   object has already been created?  If one has been created, how should
> >   the existing instance be retrieved?
> >
> It would be simpler if third party code (mpl) did not *have* to do all
> this--if it could simply assume that it was responsible for creating and
> destroying the app object.  But maybe this is naive.
Because multiple libraries all want to simultaneously to GUI stuff, there
has to be a way for all of them to coordinate.

> > * In a GUI application object has been created, how should third party
> code
> >   detect if the GUI event loop is running. It is not sufficient to call
> the
> >   relevant function methods in the GUI toolkits (like
> ``IsMainLoopRunning``)
> >   because those don't know if the GUI event loop is running through the
> >   input hook.
> >
> Again, it seems so much simpler if the third party code can be left in
> control of all this, so the question does not even arise.
> > * We might need a way for third party code to determine if it is running
> >   in IPython or not.  Currently, the only way of running GUI code in
> IPython
> >   is by using the input hook, but eventually, GUI based versions of
> IPython
> >   will allow the GUI event loop in the more traditional manner. We will
> need
> >   a way for third party code to distinguish between these two cases.
> >
> What are the non-hook methods you have in mind?  Maybe this option makes
> my proposed, or hoped-for, simplification impossible.
The two process kernel/frontend will simply start the event loop in the
kernel in the traditional way (non inputhook).  It has to do this because
the entire kernel will be based on that event loop.  We have thought about
if we could reuse the inputhook stuff there and it won't work.

> > While we are focused on other things right now (the kernel/frontend) we
> > would love to hear your thoughts on these issues.  Implementing a
> > solution shouldn't be too difficult.
> Another vague thought:  If we really need a more flexible environment,
> then maybe the way to achieve it is with a separate package or module
> that provides the API for collaboration between, e.g., ipython and mpl.
>  Perhaps all the toolkit-specific event loop code could be factored out
> and wrapped in a toolkit-neutral API.  Then, an mpl interactive backend
> would use this API regardless of whether mpl is running in a script, or
> inside ipython.  In the latter case, ipython would be using the same
> API, providing centralized knowledge of, and control over, the app
> object and the loop.  I think that such a refactoring, largely combining
> existing functionality in ipython and mpl, might not be terribly
> difficult, and might make future improvements in functionality much
> easier.  It would also make it easier for other libraries to plug into
> ipython, collaborate with mpl, etc.
This might make sense and as we move forward we should see if this makes
sense.  My first thought though is that I don't want to track yet another
project though.

> Even if the idea above is sound--and it may be completely
> impractical--the devil is undoubtedly in the details.
And there are many ones in this case.  Thanks for participating in the


> Eric
> >
> > Cheers,
> >
> > Brian
> >
> >
> >
> > On Sun, Jul 25, 2010 at 11:10 AM, Gael Varoquaux
> > <gael.varoquaux at normalesup.org <mailto:gael.varoquaux at normalesup.org>>
> > wrote:
> >
> >     With the 0.11 series of IPython, I no longer understand how the
> >     interaction with the GUI mainloop occurs:
> >
> >
> ----------------------------------------------------------------------
> >     $ ipython -wthread
> >
> >     In [1]: import wx
> >
> >     In [2]: wx.App.IsMainLoopRunning()
> >     Out[2]: False
> >
> ----------------------------------------------------------------------
> >
> >
> ----------------------------------------------------------------------
> >     $ ipython -q4thread
> >     In [1]: from PyQt4 import QtGui
> >
> >     In [2]: type(QtGui.QApplication.instance())
> >     Out[2]: <type 'NoneType'>
> >
> ----------------------------------------------------------------------
> >
> >     Is there a mainloop running or not? If not, I really don't
> >     understand how
> >     I get interactivity with GUI windows and I'd love an explaination or
> a
> >     pointer.
> >
> >     The problem with this behavior is that there is a lot of code that
> >     checks
> >     if a mainloop is running, and if not starts one. This code thus
> blocks
> >     IPython and more or less defeats the purpose of the GUI options.
> >
> >     Cheers,
> >
> >     Gaël
> >     _______________________________________________
> >     IPython-dev mailing list
> >     IPython-dev at scipy.org <mailto:IPython-dev at scipy.org>
> >     http://mail.scipy.org/mailman/listinfo/ipython-dev
> >
> >
> >
> >
> > --
> > Brian E. Granger, Ph.D.
> > Assistant Professor of Physics
> > Cal Poly State University, San Luis Obispo
> > bgranger at calpoly.edu <mailto:bgranger at calpoly.edu>
> > ellisonbg at gmail.com <mailto:ellisonbg at gmail.com>
> >
> >
> >
> > _______________________________________________
> > IPython-dev mailing list
> > IPython-dev at scipy.org
> > http://mail.scipy.org/mailman/listinfo/ipython-dev
> _______________________________________________
> IPython-dev mailing list
> IPython-dev at scipy.org
> http://mail.scipy.org/mailman/listinfo/ipython-dev

Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
bgranger at calpoly.edu
ellisonbg at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ipython-dev/attachments/20100725/8ba1a657/attachment.html>

More information about the IPython-dev mailing list