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

[Bug]: Saving a figure with indicate_inset_zoom to pdf and then pickling it causes TypeError #27805

Closed
lmarti-dev opened this issue Feb 20, 2024 · 1 comment · Fixed by #27806
Labels
topic: pickle Issues to do with pickling
Milestone

Comments

@lmarti-dev
Copy link

Bug summary

If a fig with an ax using the indicate_inset_zoom is saved to pdf and then pickled, one gets the following error:

TypeError: cannot pickle '_io.BufferedWriter' object

Code for reproduction

import pickle
import matplotlib.pyplot as plt


def plot(inset_zoom: bool, format: str):
    fig, ax = plt.subplots()
    ax.plot(
        [1, 1],
        [2, 2],
    )

    if inset_zoom:
        ax.indicate_inset_zoom(ax)

    if format is not None:
        fig.savefig(f"./test1.{format}", format=f"{format}")

    pickle.dumps(fig)


for format in (None, "png", "pdf"):
    for inset_zoom in (False, True):
        print(f"format: {format} inset_zoom {inset_zoom}")
        plot(inset_zoom, format)
        print("ok")

Actual outcome

(venv) C:\Users\Moi4\Desktop\code\test\pickle_buffwr_err>python error_with_mpl_pickle.py
format: None inset_zoom False
ok
format: None inset_zoom True
ok
format: png inset_zoom False
ok
format: png inset_zoom True
ok
format: pdf inset_zoom False
ok
format: pdf inset_zoom True
Traceback (most recent call last):
  File "C:\Users\Moi4\Desktop\code\test\pickle_buffwr_err\error_with_mpl_pickle.py", line 24, in <module>
    plot(inset_zoom, format)
  File "C:\Users\Moi4\Desktop\code\test\pickle_buffwr_err\error_with_mpl_pickle.py", line 18, in plot
    pickle.dumps(fig)
TypeError: cannot pickle '_io.BufferedWriter' object

Expected outcome

The expected outcome would be no TypeError

Additional information

Saving to pickle before saving the figure is a workaround.

Operating system

Windows 10

Matplotlib Version

3.7.1 and 3.8.3

Matplotlib Backend

TkAgg

Python version

3.10.11

Jupyter version

No response

Installation

pip

@ksunden
Copy link
Member

ksunden commented Feb 20, 2024

The culprit here appears to be these two lines in ConnectionPatch:

if renderer is not None:
self._renderer = renderer

Namely, that the ConnectionPatch object (which is used to draw the zoom lines in inset_zoom) holds a reference to to the renderer on draw.

This combined with the fact that the PDF backend holds a reference to a BytesIO object (as well as I believe at least one other unpicklable generator object... didn't trace exactly where that came from, but was able to poke it to give me a different error) means that upon drawing with the PDF backend the ConnectionPatch becomes unpicklable.

As far as I can tell, there is no reason to hold a reference here, it is never accessed. It has existed in this class since the beginning (August of 2009).

There are a handful of other places we store a renderer to an instance attribute, as a roundup:

  • offsetbox.AnnotationBbox: Added around the same time, similarly does not appear to be accessed
  • Various points within backends themselves, unlikely to be problematic
  • patheffects.PathEffectRenderer: this is the whole point of the object, and is not on an artist, so likely fine.
  • text.Text/text.Annotation: Is handled as a special case in __getstate__/__setstate__, and thus explicitly picklable.
    • I'm guessing that the other two copied Text as a template for writing the draw method, and that the attribute was never actually used for them and thus is likely safe to remove.

@ksunden ksunden added the topic: pickle Issues to do with pickling label Feb 20, 2024
ksunden added a commit to ksunden/matplotlib that referenced this issue Feb 20, 2024
As far as I can tell, these are unused, and cause problems for pickling

Closes matplotlib#27805
@QuLogic QuLogic added this to the v3.9.0 milestone Feb 21, 2024
Impaler343 pushed a commit to Impaler343/matplotlib that referenced this issue Mar 8, 2024
As far as I can tell, these are unused, and cause problems for pickling

Closes matplotlib#27805
Impaler343 pushed a commit to Impaler343/matplotlib that referenced this issue Mar 14, 2024
As far as I can tell, these are unused, and cause problems for pickling

Closes matplotlib#27805
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: pickle Issues to do with pickling
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants