Skip to content

PGF backend + savefig.bbox results in I/O error in 3.2 #16731

Closed

Description

@Psirus

Bug report

Bug summary

When using matplotlib 3.2, the PGF backend and the rcParam "savefig.bbox" set to "tight", plt.savefig error with ValueError: I/O operation on closed file. Works fine on 3.1.3.

Code for reproduction

import matplotlib as mpl
mpl.use("pgf")
import matplotlib.pyplot as plt
plt.rcParams.update({"pgf.texsystem": "lualatex", "savefig.bbox": "tight"})
fig, ax = plt.subplots()
ax.plot([1.0, 2.0, 3.0], [4.0, 5.0, 6.0])
plt.savefig("test.pdf")

I don't know if the lualatex is necessary to reproduce, I just didn't have xelatex installed. Without the savefig.bbox it works fine.

Actual outcome

Traceback (most recent call last):
  File "test.py", line 9, in <module>
    plt.savefig("test.pdf")
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/pyplot.py", line 723, in savefig
    res = fig.savefig(*args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/figure.py", line 2203, in savefig
    self.canvas.print_figure(fname, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/backend_bases.py", line 2067, in print_figure
    self.figure.draw(renderer)
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/figure.py", line 1734, in draw
    self.patch.draw(renderer)
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/artist.py", line 38, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/patches.py", line 602, in draw
    self._facecolor if self._facecolor[3] else None)
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/backends/backend_pgf.py", line 476, in draw_path
    writeln(self.fh, r"\begin{pgfscope}")
  File "/usr/local/lib/python3.7/dist-packages/matplotlib/backends/backend_pgf.py", line 118, in writeln
    fh.write(line)
ValueError: I/O operation on closed file.

Expected outcome

Works in 3.1.3.

Matplotlib version

  • Operating system: Debian Stable
  • Matplotlib version: 3.2
  • Matplotlib backend (print(matplotlib.get_backend())): pgf
  • Python version: 3.7

Installed matplotlib from pip.

Activity

  1. added
    Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
    on Mar 11, 2020
  2. added this to the v3.2.1 milestone on Mar 11, 2020
  3. tacaswell commented on Mar 11, 2020

    @tacaswell
    Member

    @Psirus I don't have pgf set up on the machine I am currently on, can you confirm it works without the tight bounding box?

  4. Psirus commented on Mar 11, 2020

    @Psirus
    ContributorAuthor

    Yes, if I remove the savefig.bbox or set it to standard, it works.

  5. tacaswell commented on Mar 11, 2020

    @tacaswell
    Member

    attn @anntzer I suspect this is related to the cleanup to the pgf code.

    I suspect the problem is that to do the 'tight' bounding box we have to render the figure twice but are not getting a fresh file handle the second time.

  6. self-assigned this
    on Mar 11, 2020
  7. PanagiotisS commented on Mar 11, 2020

    @PanagiotisS

    Hi,
    I have same (?) issue when using pgf backend, savefig with bbox, and matplotlib version 3.2.
    Matplotlib version 3.1.3 works without problem. or matplotlib version 3.2, pgf, without bbox.

    Same problem appears with python 3.6.9 when installing matplotlib through pip or with python 3.8.1 through conda env.

    Python 3.8.1 (default, Jan  8 2020, 22:29:32)
    [GCC 7.3.0] :: Anaconda, Inc. on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import matplotlib as mpl
    >>> import matplotlib.pyplot as plt
    >>> x = [1, 2, 3]
    >>> y = [5, 6, 7]
    >>> plt.plot(x, y)
    [<matplotlib.lines.Line2D object at 0x7fb0a4e1ed90>]
    >>> plt.savefig("plots/test.pdf", bbox_inches="tight")
    >>> mpl.use("pgf")
    >>> plt.savefig("plots/test.pdf", bbox_inches="tight")
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/pyplot.py", line 723, in savefig
        res = fig.savefig(*args, **kwargs)
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/figure.py", line 2203, in savefig
        self.canvas.print_figure(fname, **kwargs)
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/backend_bases.py", line 2067, in print_figure
        self.figure.draw(renderer)
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/artist.py", line 38, in draw_wrapper
        return draw(artist, renderer, *args, **kwargs)
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/figure.py", line 1734, in draw
        self.patch.draw(renderer)
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/artist.py", line 38, in draw_wrapper
        return draw(artist, renderer, *args, **kwargs)
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/patches.py", line 598, in draw
        draw_path(tpath, affine,
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 476, in draw_path
        writeln(self.fh, r"\begin{pgfscope}")
      File "/home/user/.conda/envs/mpltest/lib/python3.8/site-packages/matplotlib/backends/backend_pgf.py", line 118, in writeln
        fh.write(line)
    ValueError: I/O operation on closed file.
    >>>

    I created a new conda env where only matplotlib was installed in order to test it.

     ○ conda list
    # packages in environment at /home/user/.conda/envs/mpltest:
    #
    # Name                    Version                   Build  Channel
    _libgcc_mutex             0.1                        main
    blas                      1.0                         mkl
    ca-certificates           2019.11.28           hecc5488_0    conda-forge
    certifi                   2019.11.28               py38_0    conda-forge
    cycler                    0.10.0                   py38_0
    dbus                      1.13.12              h746ee38_0
    expat                     2.2.6                he6710b0_0
    fontconfig                2.13.1            h86ecdb6_1001    conda-forge
    freetype                  2.9.1                h8a8886c_1
    glib                      2.63.1               h5a9c865_0
    gst-plugins-base          1.14.5               h0935bb2_2    conda-forge
    gstreamer                 1.14.5               h36ae1b5_2    conda-forge
    icu                       64.2                 he1b5a44_1    conda-forge
    intel-openmp              2020.0                      166
    jpeg                      9c                h14c3975_1001    conda-forge
    kiwisolver                1.0.1            py38he6710b0_0
    ld_impl_linux-64          2.33.1               h53a641e_7
    libedit                   3.1.20181209         hc058e9b_0
    libffi                    3.2.1                hd88cf55_4
    libgcc-ng                 9.1.0                hdf63c60_0
    libgfortran-ng            7.3.0                hdf63c60_0
    libpng                    1.6.37               hbc83047_0
    libstdcxx-ng              9.1.0                hdf63c60_0
    libuuid                   2.32.1            h14c3975_1000    conda-forge
    libxcb                    1.13                 h1bed415_1
    libxml2                   2.9.9                hea5a465_1
    matplotlib                3.2.0                         1    conda-forge
    matplotlib-base           3.2.0            py38h250f245_1    conda-forge
    mkl                       2020.0                      166
    mkl-service               2.3.0            py38he904b0f_0
    mkl_fft                   1.0.15           py38ha843d7b_0
    mkl_random                1.1.0            py38h962f231_0
    ncurses                   6.2                  he6710b0_0
    numpy                     1.18.1           py38h4f9e942_0
    numpy-base                1.18.1           py38hde5b4d6_1
    openssl                   1.1.1d               h516909a_0    conda-forge
    pcre                      8.43                 he6710b0_0
    pip                       20.0.2                   py38_1
    pyparsing                 2.4.6                      py_0
    pyqt                      5.9.2            py38h05f1152_4
    python                    3.8.1                h0371630_1
    python-dateutil           2.8.1                      py_0
    qt                        5.9.7                h0c104cb_3    conda-forge
    readline                  7.0                  h7b6447c_5
    setuptools                45.2.0                   py38_0
    sip                       4.19.13          py38he6710b0_0
    six                       1.14.0                   py38_0
    sqlite                    3.31.1               h7b6447c_0
    tk                        8.6.10               hed695b0_0    conda-forge
    tornado                   6.0.3            py38h7b6447c_3
    wheel                     0.34.2                   py38_0
    xz                        5.2.4                h14c3975_4
    zlib                      1.2.11               h7b6447c_3
    (mpltest)
    
    ○ uname -a
    Linux hostname1 3.10.0-1062.12.1.el7.x86_64 #1 SMP Tue Feb 4 23:02:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
    
    ○ lsb_release -d                                                                                       
    Description:    CentOS Linux release 7.7.1908 (Core)  

    I hope this can be of use to you

  8. anntzer commented on Mar 11, 2020

    @anntzer
    Contributor

    I understand where the problem comes from, but it's going to be slightly tricky to fix so it will likely take a few days.

    Basically this comes from the fact that the pgf backend needs to interact for real with the filesystem even when saving to an in-memory BytesIO() object (both because of TeX, and because draw_image works by saving to an image and then includegraphics'ing it). This breaks the assumption I made in #14134, which is that the "dummy" renderer used for tight-layouting could just use an in-memory buffer without filesystem considerations.

  9. tacaswell commented on Mar 11, 2020

    @tacaswell
    Member

    Is the fastest path to revert #14134 for 3.2.x or is there a bunch of follow on PRs that would also need to be backed out?

  10. anntzer commented on Mar 11, 2020

    @anntzer
    Contributor

    Reverting #14134 and its followup #14216 is likely easiest for 3.2.
    edit: now done as #16732.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Release criticalFor bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.backend: pgf

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions