Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 11:02
    has2k1 commented #19040
  • 10:11
    clawfire commented #19000
  • 08:41
    dopplershift commented #19040
  • 08:09
    dopplershift commented #19043
  • 01:32
    wanganhong commented #19027
  • 01:31
    wanganhong commented #19027
  • 01:25
    wanganhong edited #19027
  • 01:25
    rfernand2 commented #19039
  • 01:14
    anntzer commented #19039
  • 01:13
    anntzer synchronize #19046
  • 00:53
    rfernand2 commented #19039
  • 00:52
    rfernand2 commented #19039
  • 00:50
    rfernand2 commented #19039
  • Nov 29 21:05
    anntzer labeled #19046
  • Nov 29 21:05
    anntzer opened #19046
  • Nov 29 21:05
    anntzer milestoned #19046
  • Nov 29 18:56
    story645 commented #19016
  • Nov 29 15:42
    anntzer labeled #19044
  • Nov 29 15:42
    anntzer labeled #19045
  • Nov 29 15:42
    anntzer labeled #19045
Thomas A Caswell
@tacaswell
sigh, which SO says
Antony Lee
@anntzer
deleteonclose was argued against (and removed from the codebase) in matplotlib/matplotlib@e407926; I'm not sure I agree but that was before my time
also https://www.riverbankcomputing.com/pipermail/pyqt/2011-August/030376.html strongly suggests that when a PyObject* gets gc'ed the underlying QObject indeed also gets destroyed
Thomas A Caswell
@tacaswell
apparently not before my time (but close)
I think the point with removing deleteonclose is that you could then end up with python objects not backed by a c++ object
Antony Lee
@anntzer
but that's already the case and we already check these with sip.isdeleted...
Thomas A Caswell
@tacaswell
we seem to do that only on the timers though?
fig = plt.figure()
plt.close('all')
fig.canvas.manager.window.show()
fig.subplots()
currently this "works"
(you might have to poke at it to get it to re-draw as it is disconnected from the stale hooks)
(wrt what close_event really means)
Thomas A Caswell
@tacaswell
leaving it as self.window.close() and adding gc.collect(2) it will clear the zombie figure
Antony Lee
@anntzer
ok but having gc.collect(1) not work and gc.collect(2) work just looks like... totally unmaintainable...
Thomas A Caswell
@tacaswell
gc.collect() also works (the default value is 2)
we used to do a more agressive gc.collect but we had users report major performance issues if they had lots of non-Matplotlib objects in their code
Antony Lee
@anntzer
ok, I see, basically we would like to have an API like "please check whether this object is now only alive through a refcycle, and if so collect it"
Thomas A Caswell
@tacaswell
but if we have the object to ask that then the answer is "no" ;)
Antony Lee
@anntzer
(which doesn't exist)
exactly
"only alive via a refcycle and this reference"
I guess the cleaner solution is indeed to have close() actually mean destroy() (the C-level object)
and let the python side catch up whenever gc runs
Thomas A Caswell
@tacaswell
It is not clear to me that that is actually better
Antony Lee
@anntzer
at least that's deterministic?
Thomas A Caswell
@tacaswell
there are some things we def want to work after closing (like save!)
Antony Lee
@anntzer
that's fine, we don't need a live qtcanvas for that
Thomas A Caswell
@tacaswell
so if we do destroy we would have to make sure that enough of the python side works or swap out the canvas (which seems funny to do)
Antony Lee
@anntzer
we could always switch to backend_agg...
(or whatever is relevant)
Thomas A Caswell
@tacaswell
also, I am 100% sure we have users abusing this
Antony Lee
@anntzer
ok, but that's actually warnable
set a flag on close, and warn if people try to ressucitate stuff
Thomas A Caswell
@tacaswell
That will hopefully bring some people out of the woodwork to comment on why this is happening :-p
Antony Lee
@anntzer
actually I don't even think saving is going to be a problem, at worse we'll have to sprinkle a few sip.isdeleted here and there, but the actual rendering is done by something fully managed by ourselves
fwiw tk and gtk3 both call destroy on the widgets on manager destruction
indeed a quick try suggests only qt supports ressucitation currently (and per the above that's basically an implementation choice)
Jody Klymak
@jklymak

@tacaswell @anntzer: So we seem to have three alternatives:

import matplotlib as mpl
fig, axs = mpl.subplots()

or

import matplotlib.figure as mfigure
fig = mfigure.figure()
axs = fig.subplots()

or

import matplotlib.figwrapper as mfigwrap
fig, axs = mfigwrap.subplots()
Number 2 seems strained. Number 3 is going to be hard to convince most folks that its better than matplotlib.pyplot
Thomas A Caswell
@tacaswell
and I do not think that number 1 is a valid option due to the implicit configuration and global state issues
Jody Klymak
@jklymak
OK, and sorry if I'm being dumb, but I don't understand why thats a problem? What wires can get crossed?
I'm definitely not arguing with you - I just am ignorant
Thomas A Caswell
@tacaswell
Jody Klymak
@jklymak
OK, I find that very confusing, because the only way I know to switch the backend is matplotlib.use
Thomas A Caswell
@tacaswell
Matplotlib has two (ish) faces, one is very application like (pyplot which "just works" guesses the right GUI etc) and the library side (which you have be more explicit with)
Antony Lee
@anntzer
it's not obvious to me we absolutely do not want to move that to the toplevel; I guess I sort of see your point but heh
Thomas A Caswell
@tacaswell
if you have not imported pyplot yet mpl.use only sets a value in rcparams
and we do some sys.modules sniffing to sort out if you have already imported pyplot and we should try to be more helpful
Jody Klymak
@jklymak
OK, but none of that happens until a call to *.figure()?
Thomas A Caswell
@tacaswell
no, it is called on import of pyplot