Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
wants to merge 1 commit into from

Conversation

mdboom
Copy link
Member

@mdboom mdboom commented Aug 8, 2013

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
Copy link
Member

efiring commented Aug 8, 2013

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

@WeatherGod
Copy link
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
Copy link
Member

efiring commented Aug 9, 2013

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

@pelson
Copy link
Member

pelson commented Aug 12, 2013

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

@mdboom
Copy link
Member Author

mdboom commented Aug 12, 2013

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
Copy link
Member Author

mdboom commented Aug 12, 2013

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

@pelson
Copy link
Member

pelson commented Aug 12, 2013

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
Copy link
Member Author

mdboom commented Aug 12, 2013

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
Copy link
Member Author

mdboom commented Sep 3, 2013

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
Member

Does PS1 exist on Windows?

@mdboom
Copy link
Member Author

mdboom commented Sep 4, 2013

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
Copy link
Member

pelson commented Sep 4, 2013

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
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
Copy link
Member

pelson commented Jan 13, 2014

@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
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
Copy link

ackalker commented Sep 3, 2014

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
Copy link

soshuai commented Mar 4, 2017

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

@adaldo
Copy link

adaldo commented Jan 10, 2018

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
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.

None yet

10 participants