Skip to content

Don't enable "interactive mode" if not at the console - #2286

Closed
mdboom wants to merge 1 commit into
matplotlib:v1.3.xfrom
mdboom:interactive
Closed

mdboom wants to merge 1 commit into
matplotlib:v1.3.xfrom
mdboom:interactive

Conversation

@mdboom

@mdboom mdboom commented Aug 8, 2013

Copy link
Copy Markdown
Member

This is a very small patch, but one which probably deserves a lot of discussion, as it's a rather core part of the code and an area that predates my arrival on the scene.

Currently, when the rcParam interactive is set to True, it is impossible to display anything using a simple script:

from matplotlib import pyplot as plt

plt.plot([1,2,3])
plt.show()

while True:
   pass

(The infinite loop makes no difference, I just want to demonstrate that even by blocking the interpreter, nothing is shown). All GUI backends (excepting macosx, which I didn't test) display nothing, with the exception of TkAgg which displays an empty window.

I think this is not a good situation, because a user may set interactive to True because they prefer that behavior at the console, but will then be surprised when their standalone scripts break. This was the source of an internal bug report at STScI, that took even myself a while to track down.

The fix here is to disable interactive mode if not at an interactive prompt (detected by checking the presence of sys.ps1).

Are there any negative consequences to this that I'm not envisioning? I have tested and found no behavior change in any backend within IPython, both "classic" and notebook. Is there a use case for "interactive" outside of a standard console that I'm not aware of?

Cc: @fperez, @efiring, @stsci-sienkiew

FWIW: interactive mode, in its "native habitat" at the console seems to work most places now. Only wx doesn't work in the vanilla python console (but it does in IPython).

@efiring

efiring commented Aug 8, 2013

Copy link
Copy Markdown
Member

It looks reasonable, but probably needs to be tested with things like Spyder.

@WeatherGod

Copy link
Copy Markdown
Member

I know of some people who have been using plt.ion() in their stand-alone
scripts (with a blocking show towards the end) as a quick-n-dirty way of
throwing up a plots as a long-running process proceeds. I don't know if
what they did was ultimately successful or not. I will have to follow up
with them on this.

Is there a difference between setting interactive mode through the rcparam
at startup and calling plt.ion() later?

@efiring

efiring commented Aug 9, 2013

Copy link
Copy Markdown
Member

No. plt.ion() calls matplotlib.interactive() which sets the rcparam.

@pelson

pelson commented Aug 12, 2013

Copy link
Copy Markdown
Member

👍 for making the change. 👎 for doing it against v1.3.

@mdboom

mdboom commented Aug 12, 2013

Copy link
Copy Markdown
Member Author

I tried this in Spyder. There is no change in behavior with this patch when running lines in its embedded console. When running files in a new interpreter and "interactive" is True, nothing is displayed without this patch applied. I will bring this PR to the attention of the Spyder team as well, in case they have any thoughts.

@pelson: I'd agree with you (not on v1.3) if there is a conceivable use case in which interactive mode not at a console makes sense. But as it stands, this just seems like a surprising bug that I'd like to fix sooner rather than later. I'll bring this to the mailing list to try to get more comment and involvement.

@mdboom

mdboom commented Aug 12, 2013

Copy link
Copy Markdown
Member Author

Also, @minrk, @ellisonbg, @fperez: It would be great if an IPython expert would have a look at this.

@pelson

pelson commented Aug 12, 2013

Copy link
Copy Markdown
Member

But as it stands, this just seems like a surprising bug that I'd like to fix sooner rather than later

it's a rather core part of the code and an area that predates my arrival on the scene.

Seems to me that it has been here long enough that I wouldn't want to change it as a bug fix, but as a behavioural feature enhancement. I'd be much happier if this went through as much testing on master as possible before we go to a v1.4. Sorry @mdboom...

@mdboom mdboom closed this Aug 12, 2013
@mdboom mdboom reopened this Aug 12, 2013
@mdboom

mdboom commented Aug 12, 2013

Copy link
Copy Markdown
Member Author

I think if there's even a single use case for the current behavior, I'm happy to put this off. And I'm willing to give it some time for someone with such a use case to present. Otherwise, all I've seen thus far is the (major) downside of the current behavior.

@mdboom

mdboom commented Sep 3, 2013

Copy link
Copy Markdown
Member Author

I've gone ahead and cherry-picked this into master -- I've come around that this probable shouldn't be on 1.3.x.

@mdboom mdboom closed this Sep 3, 2013
@dmcdougall

Copy link
Copy Markdown
Member

Does PS1 exist on Windows?

@mdboom

mdboom commented Sep 4, 2013

Copy link
Copy Markdown
Member Author

I think so, because it refers to the Python prompt, not the shell prompt, but I think you're right that we should check. Any Windows users able to confirm?

@pelson

pelson commented Sep 4, 2013

Copy link
Copy Markdown
Member

I've come around that this probable shouldn't be on 1.3.x.

Thanks for merging @mdboom - this way at least we get as much testing as possible with this new change so that we can hopefully catch any skeletons.

@cimarronm

Copy link
Copy Markdown
Contributor

This breaks much of the functionality I have used in the past where there are functions I have to call which have a show() in them (and I cannot modify the code to add a block argument to the plt.show() function) but I do not want them to block so that all plots show at once.

I have used something like the following to do so

plt.ion() # turn on interactive mode to prevent blocking

# calling various functions which have plt.show in them
plot1_module()
plot2_module()
plot3_module()

# now turn off interactive and show all plots
plt.ioff()
plt.show()

It seems we should have a way to globally enable/disable the blocking of show to enable this sort of functionality (otherwise I will just have to implement the hack to add sys.ps1 to get around this change). What do you guys think?

@pelson

pelson commented Jan 13, 2014

Copy link
Copy Markdown
Member

@cimarronm - adding a show "block" rcParam is conceivable - I wonder how many people would use it though (I wonder that about a lot of the rcParams to be fair). Perhaps in this case, just patching plt.show would be as clear:

import mock

# patch out plt.show so that the calling modules don't actually do anything when running plt.show().
with mock.patch('matplotlib.pyplot.show') as no_show:
   plot1_module()
   plot2_module()
   plot3_module()

plt.show()

I think your case is reasonable (perhaps the called modules should be factorised anyway), but pretty edge-case, so I'm not sure how much functionality we want to add (and therefore maintain) to get the desired behaviour.

Anyway, hope this is useful.

Cheers,

@tacaswell

Copy link
Copy Markdown
Member

From watching SO, this use case is far less edgey than you would hope.

A common want is to have a stand-alone script that pops up a bunch of interactive windows, blocks till they are closed, and repeat.

Making this sane/easy to do is one of the end goals of the work in #2624 .

@ackalker

ackalker commented Sep 3, 2014

Copy link
Copy Markdown

Please reconsider (alternatives to) this change, the bug referenced above this comment indicates that the change as currently implemented is very Python(-session)-centric: there are other users of matplotlib out there, like Julia's PyPlot.jl, which uses libpython and not a standalone interpreter process to interface to matplotlib.

I would suggest an initialisation API which interested users of matplotlib should use to indicate their need to distinguish between interactive and non-interactive use, with the old behaviour as a compatible default.

@soshuai

soshuai commented Mar 4, 2017

Copy link
Copy Markdown

It was so sad for my English was very poor,can you tell me this content use Chinese.

@adaldo

adaldo commented Jan 10, 2018

Copy link
Copy Markdown

Let me add that I am using Matplotlib with ROS and rospy to dynamically show the position of some points while my ROS nodes (which are Python scripts) are running. This is not possible anymore if interactive mode is disabled out of a console.

@tacaswell

Copy link
Copy Markdown
Member

@adaldo This change was reverted in 061728a for 1.4.1. I think the only version with this change is 1.4.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants