0

I'm also having problem with pickling and then unpicking and displaying a Matplotlib figure in Python 3.7 and Matplotlib 3.1.3.

I save my figures as (simplified code):

fig, ax = plt.subplots()
fig.show() #works fine
list_figs.append(fig)
output = {
    "figures": list_figs
}
with open( f"mPair.pkl", "wb" ) as f:
    pickle.dump( output, f )
res = pickle.load( open( f"mPair.pkl", "rb" ) )
res["figures"][0].show() #does not work

The code works fine if I directly show the figure but after pickling/unpickling I get:

Traceback (most recent call last):
  File "/Users/xx/opt/anaconda3/envs/nengo3/lib/python3.7/site-packages/IPython/core/interactiveshell.py", line 3331, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-3-4759ba430504>", line 1, in <module>
    res1[ "fig_post" ].show()
  File "/Users/xx/opt/anaconda3/envs/nengo3/lib/python3.7/site-packages/matplotlib/figure.py", line 438, in show
    "created by pyplot.figure()." % err)
AttributeError: 'NoneType' object has no attribute 'manager'
Figure.show works only for figures managed by pyplot, normally created by pyplot.figure()
Thomas Tiotto
  • 379
  • 1
  • 3
  • 12
  • [Classes, functions, and methods cannot be pickled -- if you pickle an object, the object's class is not pickled, just a string that identifies what class it belongs to.](https://wiki.python.org/moin/UsingPickle) – Paul Brodersen Apr 20 '20 at 13:52
  • The following/rest is just an educated guess: I would assume that the figure manager depends on the backend, which is determined at runtime. However, pickle -- being general purpose -- has obviously no idea how to detect the backend being used, nor does it even know that it should find out, and then initialize the appropriate manager. – Paul Brodersen Apr 20 '20 at 13:52
  • Is there no way to initialise the Matplotlib manager explicitly? Also, I seem to remember reading that Matplotlib has had pickling support for years. – Thomas Tiotto Apr 20 '20 at 14:11
  • If the latter is the case, then you know more than me. However, apparently there is a workaround: you can use the manager from a different figure to display a pickled figure, as per [this SO answer](https://stackoverflow.com/a/54579616/2912349). – Paul Brodersen Apr 20 '20 at 14:21
  • [You are right and they should be picklable](https://matplotlib.org/3.1.0/users/prev_whats_new/whats_new_1.2.html#figures-are-picklable). Raise an issue on their github. – Paul Brodersen Apr 20 '20 at 14:26

1 Answers1

0

what happens if you do not show the figure and save to pickle before showing, i.e. if you run this:

fig, ax = plt.subplots()
#fig.show() #works fine
list_figs.append(fig)
output = {
    "figures": list_figs
}
with open( f"mPair.pkl", "wb" ) as f:
    pickle.dump( output, f )
res = pickle.load( open( f"mPair.pkl", "rb" ) )
res["figures"][0].show() #does it work?
Siamak
  • 15
  • 2