repeated calls to show() are now OK?

It seems that every couple of weeks, someone understandably asks why one can't call show() more than once in a script or session. However, I think that at least on all non-Mac backends, it now works. I have tested it (using ipython, with no threading) on:

qtagg, qt4agg, wx, wxagg, gtk, gtkagg, tkagg, and fltkagg

The only glitch is what appears to be an unrelated bug in fltkagg: clicking on the window-kill button of a sole open window doesn't have any effect.

(There is also the difference in behavior: tkagg and fltkagg calls to show are non-blocking, while all the other backends block.)

What is the situation with respect to the Mac backends?

Is it time for us to change our documentation, and officially support the use of multiple calls to show()? If we can do it, I think it would remove one of the main stumbling blocks for newcomers.

Eric

I don't have a problem allowing/supporting it, but it may be tricky if
we expect it to have the same blocking/non-blocking behavior across
backends. Ie, for the script that does

for i in range(10):
   plt.plot(np.random.rand(10), 'o')
   plt.show()

many users expect that to be blocking on each call to show and the
script to continue after closing each figure. My guess is that
different backends on different platforms might show different
behavior -- some may block, others not. I haven't looked at your
changes yet, but what is your opinion on this issue?

JDH

···

On Fri, Jun 11, 2010 at 2:56 PM, Eric Firing <efiring@...229...> wrote:

Is it time for us to change our documentation, and officially support
the use of multiple calls to show()? If we can do it, I think it would
remove one of the main stumbling blocks for newcomers.

Is it time for us to change our documentation, and officially support
the use of multiple calls to show()? If we can do it, I think it would
remove one of the main stumbling blocks for newcomers.

I don't have a problem allowing/supporting it, but it may be tricky if
we expect it to have the same blocking/non-blocking behavior across
backends. Ie, for the script that does

for i in range(10):
    plt.plot(np.random.rand(10), 'o')
    plt.show()

many users expect that to be blocking on each call to show and the
script to continue after closing each figure. My guess is that
different backends on different platforms might show different
behavior -- some may block, others not. I haven't looked at your
changes yet, but what is your opinion on this issue?

The only change I made was to the wx backend. (The basic idea was provided in a patch submitted nearly 3 years ago.) All the other non-Mac backends already handled multiple calls to show.

I agree that the difference in blocking behavior is still a problem. I think that what we should do for now, *if* multiple calls to show work on the Mac (which I can't easily test), is change the documentation to correspond to the present situation, highlighting the real problem of different blocking behavior.

Longer term, the ideal would be to universally support both blocking and non-blocking behavior, since there are valid use-cases for each. It would have to be coordinated with ipython. I suspect it is easier to add a blocking option to the non-blockers than to give the blockers a non-block option. I really don't know whether we are going to be able to make major progress on this, though. Guis are a pain, and multiple gui toolkits interacting with multiple environments yield major pain and frustration.

Eric

···

On 06/11/2010 10:09 AM, John Hunter wrote:

On Fri, Jun 11, 2010 at 2:56 PM, Eric Firing<efiring@...229...> wrote:

JDH

I agree that the difference in blocking behavior is still a
problem. I think that what we should do for now, *if* multiple
calls to show work on the Mac (which I can't easily test), is
change the documentation to correspond to the present situation,
highlighting the real problem of different blocking behavior.

On Mac OS X, the MacOSX native backend supports multiple calls to show(). Each call to show() blocks, and show() returns when all figures are closed by the user.

With TkAgg on Mac OS X, the first call to show() blocks, and returns when all figures are closed by the user. However, subsequent calls to show() return immediately.

With GtkCairo on Mac OS X, each call to show() blocks, so show() can be called repeatedly. However, after closing all windows, show() does not return unless the user presses ctrl-c. This may not be so difficult to fix though. Basically, we need to keep track of how many windows are open at any given point, and tell the GTK main loop to exit when the number of windows reaches zero (this is how the MacOSX native backend does it).

--Michiel.

I agree that the difference in blocking behavior is still a
problem. I think that what we should do for now, *if* multiple
calls to show work on the Mac (which I can't easily test), is
change the documentation to correspond to the present situation,
highlighting the real problem of different blocking behavior.

On Mac OS X, the MacOSX native backend supports multiple calls to show(). Each call to show() blocks, and show() returns when all figures are closed by the user.

OK, so this sounds like the standard blocking behavior, just like gtk*, wx*, and qt* on Linux.

With TkAgg on Mac OS X, the first call to show() blocks, and returns when all figures are closed by the user. However, subsequent calls to show() return immediately.

This is anomalous, then; on linux, no call to show blocks with tkagg. Puzzling difference.

With GtkCairo on Mac OS X, each call to show() blocks, so show() can be called repeatedly. However, after closing all windows, show() does not return unless the user presses ctrl-c. This may not be so difficult to fix though. Basically, we need to keep track of how many windows are open at any given point, and tell the GTK main loop to exit when the number of windows reaches zero (this is how the MacOSX native backend does it).

I wasn't even aware of this backend; but sure enough, I have it on linux, and it works the same as gtkagg et al.

Why would it behave differently on OS X, with the need for the ctrl-C?

If you have TkAgg and GtkCairo, does it mean you also have GtkAgg? If so, I would expect it to behave like GtkCairo.

Thanks for the testing.

Eric

···

On 06/11/2010 10:02 PM, Michiel de Hoon wrote:

--Michiel.

If I remove the _needmain stuff in the show() function in the TkAgg backend, then each call to show() blocks on Mac OS X with the TkAgg backend, which (in my understanding) is the desired behavior. I don't know the purpose of _needmain in the show() function, other than to disallow multiple calls to show().

--Michiel.

···

--- On Sat, 6/12/10, Eric Firing <efiring@...229...> wrote:

> With TkAgg on Mac OS X, the first call to show()
> blocks, and returns when all figures are closed by the user.
> However, subsequent calls to show() return immediately.

This is anomalous, then; on linux, no call to show blocks
with tkagg.
Puzzling difference.

I committed a change to backend_tkagg that leaves the show functionality exactly as it is at present, but that facilitates testing of a simpler version that I think is more consistent with the other backends and with what we want. (I have appended the whole function to this message--see below for additional explanation.)

I have also done some more exploration and testing, and here are my tentative conclusions:

1) We should aim for a show() that blocks until all windows are closed, on all backends, and in all environments. I think this is clearly something that many users would like; it has reasonable use cases; and it is simple, consistent, and easy to explain.

2) The big problem is the "in all environments" part of that statement. We probably can't achieve the goal, but I suspect that over the long term we can approach it, and the result will be "good enough".

3) As a step in that direction, I would like to see enough testing of Tk with show(block=True) so that, if it works, we can transition towards that behavior as the default, deprecate the old behavior, and eventually eliminate it. Presently, TkAgg is most anomalous among the major backends.

4) Leaving the documentation (all in the FAQ) with its caution against anything but a single show() at the end of a script is fine for 1.0; supporting multiple calls to a blocking show under mildly restrictive conditions is a reasonable goal for a subsequent release.

Eric

···

On 06/12/2010 05:37 AM, Michiel de Hoon wrote:

--- On Sat, 6/12/10, Eric Firing<efiring@...229...> wrote:

With TkAgg on Mac OS X, the first call to show()
blocks, and returns when all figures are closed by the user.
However, subsequent calls to show() return immediately.

This is anomalous, then; on linux, no call to show blocks
with tkagg.
Puzzling difference.

If I remove the _needmain stuff in the show() function in the TkAgg backend, then each call to show() blocks on Mac OS X with the TkAgg backend, which (in my understanding) is the desired behavior. I don't know the purpose of _needmain in the show() function, other than to disallow multiple calls to show().

--Michiel.

------------------------------------------------
def show(block=False):
     """
     Show all figures.

     Temporary, experimental kwarg *block* defaults to False to
     provide the behavior present throughout mpl history to date:
     interactive mode is forced on, and show does not block.

     Set *block* to True to test the proposed new behavior,
     consistent with other backends, in which show does not affect
     interactive mode, and always blocks until all figures are closed.
     In addition, the rcParam['tk.pythoninspect'] is ignored.

     Use this kwarg only for testing; other backends do not accept
     a kwarg to show, and might never do so.
     """
     for manager in Gcf.get_all_fig_managers():
         manager.show()
     if block:
         # proposed new behavior; seems to make this backend consistent
         # with others, with no drawbacks identified yet.
         Tk.mainloop()
     else:
         # long-time behavior: non-blocking, forces interactive mode
         import matplotlib
         matplotlib.interactive(True)
         if rcParams['tk.pythoninspect']:
             os.environ['PYTHONINSPECT'] = '1'
         if show._needmain:
             Tk.mainloop()
             show._needmain = False

show._needmain = True # This can go away if we eliminate block=False option.

So on Linux, show(block=True) blocks but show(block=False) doesn't? If matplotlib is in interactive mode, does show(block=True) still block? Because if matplotlib is in interactive mode, then the call to matplotlib.interactive(True) shouldn't make a difference, and I would expect show(block=True) and show(block=False) to behave the same way.

--Michiel.

···

--- On Sat, 6/12/10, Eric Firing <efiring@...229...> wrote:

From: Eric Firing <efiring@...229...>
Subject: Re: [matplotlib-devel] repeated calls to show() are now OK?
To: "Michiel de Hoon" <mjldehoon@...42...>
Cc: "John Hunter" <jdh2358@...149...>, "matplotlib development list" <matplotlib-devel@lists.sourceforge.net>
Date: Saturday, June 12, 2010, 11:32 PM
On 06/12/2010 05:37 AM, Michiel de > Hoon wrote:
> --- On Sat, 6/12/10, Eric Firing<efiring@...229...> > wrote:
>>> With TkAgg on Mac OS X, the first call to
show()
>>> blocks, and returns when all figures are
closed by the user.
>>> However, subsequent calls to show() return
immediately.
>>
>> This is anomalous, then; on linux, no call to show
blocks
>> with tkagg.
>> Puzzling difference.
>
> If I remove the _needmain stuff in the show() function
in the TkAgg backend, then each call to show() blocks on Mac
OS X with the TkAgg backend, which (in my understanding) is
the desired behavior. I don't know the purpose of _needmain
in the show() function, other than to disallow multiple
calls to show().
>
> --Michiel.
>

I committed a change to backend_tkagg that leaves the show
functionality exactly as it is at present, but that
facilitates testing of a simpler version that I think is
more consistent with the other backends and with what we
want. (I have appended the whole function to this
message--see below for additional explanation.)

I have also done some more exploration and testing, and
here are my tentative conclusions:

1) We should aim for a show() that blocks until all windows
are closed, on all backends, and in all environments.
I think this is clearly something that many users would
like; it has reasonable use cases; and it is simple,
consistent, and easy to explain.

2) The big problem is the "in all environments" part of
that statement. We probably can't achieve the goal,
but I suspect that over the long term we can approach it,
and the result will be "good enough".

3) As a step in that direction, I would like to see enough
testing of Tk with show(block=True) so that, if it works, we
can transition towards that behavior as the default,
deprecate the old behavior, and eventually eliminate
it. Presently, TkAgg is most anomalous among the major
backends.

4) Leaving the documentation (all in the FAQ) with its
caution against anything but a single show() at the end of a
script is fine for 1.0; supporting multiple calls to a
blocking show under mildly restrictive conditions is a
reasonable goal for a subsequent release.

Eric

------------------------------------------------
def show(block=False):
"""
Show all figures.

Temporary, experimental kwarg \*block\*

defaults to False to
provide the behavior present throughout mpl
history to date:
interactive mode is forced on, and show does
not block.

Set \*block\* to True to test the proposed new

behavior,
consistent with other backends, in which show
does not affect
interactive mode, and always blocks until all
figures are closed.
In addition, the rcParam['tk.pythoninspect']
is ignored.

Use this kwarg only for testing; other

backends do not accept
a kwarg to show, and might never do so.
"""
for manager in Gcf.get_all_fig_managers():
manager.show()
if block:
# proposed new behavior; seems
to make this backend consistent
# with others, with no
drawbacks identified yet.
Tk.mainloop()
else:
# long-time behavior:
non-blocking, forces interactive mode
import matplotlib
matplotlib.interactive(True)
if
rcParams['tk.pythoninspect']:

os.environ['PYTHONINSPECT'] = '1'
if show._needmain:
Tk.mainloop()
show._needmain =
False

show._needmain = True # This can go away
if we eliminate block=False option.

So on Linux, show(block=True) blocks but show(block=False) doesn't? If matplotlib is in interactive mode, does show(block=True) still block? Because if matplotlib is in interactive mode, then the call to matplotlib.interactive(True) shouldn't make a difference, and I would expect show(block=True) and show(block=False) to behave the same way.

Except that with block=False there is that _needmain flag. And as you noted earlier, it blocks the first time, but not after that. Somehow, I had previously missed the fact that it did block on the first call, so I did not realize that the tkagg behavior was identical on linux and mac, as one would expect.

Eric

···

On 06/12/2010 08:12 PM, Michiel de Hoon wrote:

--Michiel.

--- On Sat, 6/12/10, Eric Firing<efiring@...229...> wrote:

From: Eric Firing<efiring@...229...>
Subject: Re: [matplotlib-devel] repeated calls to show() are now OK?
To: "Michiel de Hoon"<mjldehoon@...42...>
Cc: "John Hunter"<jdh2358@...149...>, "matplotlib development list"<matplotlib-devel@lists.sourceforge.net>
Date: Saturday, June 12, 2010, 11:32 PM
On 06/12/2010 05:37 AM, Michiel de >> Hoon wrote:

--- On Sat, 6/12/10, Eric Firing<efiring@...229...> >> wrote:

With TkAgg on Mac OS X, the first call to

show()

blocks, and returns when all figures are

closed by the user.

However, subsequent calls to show() return

immediately.

This is anomalous, then; on linux, no call to show

blocks

with tkagg.
Puzzling difference.

If I remove the _needmain stuff in the show() function

in the TkAgg backend, then each call to show() blocks on Mac
OS X with the TkAgg backend, which (in my understanding) is
the desired behavior. I don't know the purpose of _needmain
in the show() function, other than to disallow multiple
calls to show().

--Michiel.

I committed a change to backend_tkagg that leaves the show
functionality exactly as it is at present, but that
facilitates testing of a simpler version that I think is
more consistent with the other backends and with what we
want. (I have appended the whole function to this
message--see below for additional explanation.)

I have also done some more exploration and testing, and
here are my tentative conclusions:

1) We should aim for a show() that blocks until all windows
are closed, on all backends, and in all environments.
I think this is clearly something that many users would
like; it has reasonable use cases; and it is simple,
consistent, and easy to explain.

2) The big problem is the "in all environments" part of
that statement. We probably can't achieve the goal,
but I suspect that over the long term we can approach it,
and the result will be "good enough".

3) As a step in that direction, I would like to see enough
testing of Tk with show(block=True) so that, if it works, we
can transition towards that behavior as the default,
deprecate the old behavior, and eventually eliminate
it. Presently, TkAgg is most anomalous among the major
backends.

4) Leaving the documentation (all in the FAQ) with its
caution against anything but a single show() at the end of a
script is fine for 1.0; supporting multiple calls to a
blocking show under mildly restrictive conditions is a
reasonable goal for a subsequent release.

Eric

------------------------------------------------
def show(block=False):
     """
     Show all figures.

     Temporary, experimental kwarg *block*
defaults to False to
     provide the behavior present throughout mpl
history to date:
     interactive mode is forced on, and show does
not block.

     Set *block* to True to test the proposed new
behavior,
     consistent with other backends, in which show
does not affect
     interactive mode, and always blocks until all
figures are closed.
     In addition, the rcParam['tk.pythoninspect']
is ignored.

     Use this kwarg only for testing; other
backends do not accept
     a kwarg to show, and might never do so.
     """
     for manager in Gcf.get_all_fig_managers():
         manager.show()
     if block:
         # proposed new behavior; seems
to make this backend consistent
         # with others, with no
drawbacks identified yet.
         Tk.mainloop()
     else:
         # long-time behavior:
non-blocking, forces interactive mode
         import matplotlib
         matplotlib.interactive(True)
         if
rcParams['tk.pythoninspect']:

os.environ['PYTHONINSPECT'] = '1'
         if show._needmain:
             Tk.mainloop()
             show._needmain =
False

show._needmain = True # This can go away
if we eliminate block=False option.

I now tried the remaining backends on Mac OS X. With the Qt4Agg and WxAgg backends, show() can be called repeatedly and blocks each time. The FltkAgg backend shows the same behavior as Tkagg. The implementation of show() in the FltkAgg backend uses the same _needmain as TkAgg. If I remove the _needmain stuff, then show() can be called multiple times with FltkAgg, blocking each time.

--Michiel.

···

--- On Fri, 6/11/10, Eric Firing <efiring@...229...> wrote:

I agree that the difference in blocking behavior is still a
problem. I think that what we should do for now, *if* multiple
calls to show work on the Mac (which I can't easily test), is
change the documentation to correspond to the present situation,
highlighting the real problem of different blocking behavior.

Something that I have noticed:
When using TkAgg (python 2.5, OSX/ppc, mpl 99.0), isinteractive() switches from False to True after the first call to show() (see below). When I switch back ends, e.g. to Qt4, this change does not happen until I do it myself through ion(). This was reproduceable on my intel mac, but since updating to 99.1.1 (from source rather than Fink), I’ve broken the Tk backend. Hope this helps; it may be a naive observation.

In [2]: import matplotlib as mpl

In [3]: mpl.use(‘TkAgg’)

In [4]: import pylab as plt

In [5]: plt.isinteractive()
Out[5]: False

In [6]: plt.plot([0,1])
Out[6]: [<matplotlib.lines.Line2D object at 0x1dee1f0>]

In [7]: plt.show()

In [8]: plt.isinteractive()
Out[8]: True

···

On Sun, Jun 13, 2010 at 9:36 AM, Michiel de Hoon <mjldehoon@…42…> wrote:

— On Fri, 6/11/10, Eric Firing <efiring@…229…> wrote:

I agree that the difference in blocking behavior is still a

problem. I think that what we should do for now, if multiple

calls to show work on the Mac (which I can’t easily test), is

change the documentation to correspond to the present situation,

highlighting the real problem of different blocking behavior.

I now tried the remaining backends on Mac OS X. With the Qt4Agg and WxAgg backends, show() can be called repeatedly and blocks each time. The FltkAgg backend shows the same behavior as Tkagg. The implementation of show() in the FltkAgg backend uses the same _needmain as TkAgg. If I remove the _needmain stuff, then show() can be called multiple times with FltkAgg, blocking each time.

–Michiel.


ThinkGeek and WIRED’s GeekDad team up for the Ultimate

GeekDad Father’s Day Giveaway. ONE MASSIVE PRIZE to the

lucky parental unit. See the prize list and enter to win:

http://p.sf.net/sfu/thinkgeek-promo


Matplotlib-devel mailing list

Matplotlib-devel@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Something that I have noticed:
When using TkAgg (python 2.5, OSX/ppc, mpl 99.0), isinteractive()
switches from False to True after the first call to show() (see below).
When I switch back ends, e.g. to Qt4, this change does not happen until
I do it myself through ion(). This was reproduceable on my intel mac,
but since updating to 99.1.1 (from source rather than Fink), I've broken
the Tk backend. Hope this helps; it may be a naive observation.

Not naive at all--this is one of the odd, and I think very undesirable, aspects of present TkAgg show() behavior. It is eliminated by my proposed change.

Eric

···

On 06/13/2010 07:39 AM, Daniel Welling wrote:

In [2]: import matplotlib as mpl

In [3]: mpl.use('TkAgg')

In [4]: import pylab as plt

In [5]: plt.isinteractive()
Out[5]: False

In [6]: plt.plot([0,1])
Out[6]: [<matplotlib.lines.Line2D object at 0x1dee1f0>]

In [7]: plt.show()

In [8]: plt.isinteractive()
Out[8]: True

On Sun, Jun 13, 2010 at 9:36 AM, Michiel de Hoon <mjldehoon@…42… > <mailto:mjldehoon@…42…>> wrote:

    — On Fri, 6/11/10, Eric Firing <efiring@…229… > <mailto:efiring@…229…>> wrote:
     > I agree that the difference in blocking behavior is still a
     > problem. I think that what we should do for now, *if* multiple
     > calls to show work on the Mac (which I can't easily test), is
     > change the documentation to correspond to the present situation,
     > highlighting the real problem of different blocking behavior.

    I now tried the remaining backends on Mac OS X. With the Qt4Agg and
    WxAgg backends, show() can be called repeatedly and blocks each
    time. The FltkAgg backend shows the same behavior as Tkagg. The
    implementation of show() in the FltkAgg backend uses the same
    _needmain as TkAgg. If I remove the _needmain stuff, then show() can
    be called multiple times with FltkAgg, blocking each time.

    --Michiel.

    ------------------------------------------------------------------------------
    ThinkGeek and WIRED's GeekDad team up for the Ultimate
    GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the
    lucky parental unit. See the prize list and enter to win:
    http://p.sf.net/sfu/thinkgeek-promo
    _______________________________________________
    Matplotlib-devel mailing list
    Matplotlib-devel@lists.sourceforge.net
    <mailto:Matplotlib-devel@lists.sourceforge.net>
    https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the
lucky parental unit. See the prize list and enter to win:
http://p.sf.net/sfu/thinkgeek-promo

_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel