Skip to content

IPython is always imported by pyplot, if present #5037

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

Closed
efiring opened this issue Sep 9, 2015 · 6 comments · Fixed by #5038
Closed

IPython is always imported by pyplot, if present #5037

efiring opened this issue Sep 9, 2015 · 6 comments · Fixed by #5038
Assignees
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Milestone

Comments

@efiring
Copy link
Member

efiring commented Sep 9, 2015

When IPython is present, the import time for pyplot is roughly doubled because IPython is imported by install_repl_displayhook(). This is true even with matplotlib.use('agg'), so it will affect all scripts using pyplot.

@efiring efiring added Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. status: needs patch labels Sep 9, 2015
@efiring efiring added this to the next point release milestone Sep 9, 2015
tacaswell added a commit to tacaswell/matplotlib that referenced this issue Sep 9, 2015
This prevents importing IPython if it is not already imported.

closes matplotlib#5037
@tacaswell tacaswell self-assigned this Sep 9, 2015
@OceanWolf
Copy link
Member

Hmm, going back to what I said in the line comments of #4506, lets control this auto-redraw based on a simple rcParam check rather than using iPython...

@tacaswell
Copy link
Member

There are two ways to deal with clearing the stale state. Either when the figure comes stale it can tell the canvas to schedule a re-draw at it's next opportunity (which is what happens currently if you are not in IPython) and the other is that some external loop comes around and asks the figures if they are stale, and if so, triggers the canvas to re-draw.

I very much prefer option 2 as it puts control of the draw cadence in the hands of the event loop that is running the show, instead of mpl constantly poking at the canvas. It prevents any possibility of the nasty infinite draw-triggering-draw loops that we had to deal with (but I think those are all sorted out for the backends we ship).

The plain python repl does not have a convenient place to hook a callback function into, hence in that case we have to use the push pattern.

I don't see how in either case an rcparam helps deal with when to trigger asynchronous draws.

@efiring
Copy link
Member Author

efiring commented Sep 9, 2015

It's greatly improved, but I'm still seeing a considerable increase in import time from 1.4.3 to master, with #5038 included. The number of function calls has gone from 179,087 to 252,421, and the time is still about 100 ms longer (280 to 380) on my Linux VM. The increase is split between the matplotlib.__init__ and the pyplot, with a somewhat larger fractional contribution from the latter. (This is based on stats from a single run with kernprof.) Has our LOC count increased by this much? About 40%? I wouldn't think so.

@tacaswell
Copy link
Member

according to git we are net +22k LoC, but a lot of that is probably svgs

22:41 $ git diff v1.4.3 --shortstat
 2617 files changed, 243561 insertions(+), 220919 deletions(-)

@mdehoon
Copy link
Contributor

mdehoon commented Sep 9, 2015

There are two ways to deal with clearing the stale state. Either when the figure comes stale it can tell the canvas to schedule a re-draw at its next opportunity (which is what happens currently if you are not in IPython) and the other is that some external loop comes around and asks the figures if they are stale, and if so, triggers the canvas to re-draw.

Option 1 is the traditional way of organizing event loops on Windows, Mac, X11. I would suggest to consider carefully why matplotlib would need an approach different from other GUI programs.

The plain python repl does not have a convenient place to hook a callback function into, hence in that case we have to use the push pattern.

I believe you were looking for a function that is called when Python is waiting for the next command?
If so, then at least with tkagg you could use Tkinter's after_idle.

@OceanWolf
Copy link
Member

Yes, I thought we had draw_idle to do exactly that. It works like a mailbox flag. When you change some properties that means we need the artist redrawn, we raise the flag to say "come here", and notify the system that it needs to make a round when it has free time. Based on previous comments regarding embedding, I think we would want to use an rcParam to control whether the artist will raising of the flag will automatically request a draw_idle. As with the mail, If the draw_idle execution has not yet begun, another request for it will just represent a no-op.

Anyway, not a biggie, I think we can change to this or some other behaviour safely enough at a later point... but I thought if we needed to get rid of that IPython import now, then we can/should do it this way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants