Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Save to .pdf doesn't work in 2.1.0 #9390

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
narimiran opened this issue Oct 13, 2017 · 11 comments
Closed

Save to .pdf doesn't work in 2.1.0 #9390

narimiran opened this issue Oct 13, 2017 · 11 comments
Labels
Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Milestone

Comments

@narimiran
Copy link

Bug report

Bug summary

fig.savefig(filename.pdf) doesn't work like in the previous versions

Code for reproduction

fig, ax = plt.subplots()
ax.plot([5, 4, 2, 3])
fig.savefig('test.pdf')

Actual outcome

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-5c7237786c15> in <module>()
      1 fig, ax = plt.subplots()
      2 ax.plot([5, 4, 2, 3])
----> 3 fig.savefig('test.pdf')

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\figure.py in savefig(self, fname, **kwargs)
   1812             self.set_frameon(frameon)
   1813 
-> 1814         self.canvas.print_figure(fname, **kwargs)
   1815 
   1816         if frameon:

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
   2257                 orientation=orientation,
   2258                 bbox_inches_restore=_bbox_inches_restore,
-> 2259                 **kwargs)
   2260         finally:
   2261             if bbox_inches and restore_bbox:

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\backends\backend_pdf.py in print_pdf(self, filename, **kwargs)
   2590                 RendererPdf(file, image_dpi, height, width),
   2591                 bbox_inches_restore=_bbox_inches_restore)
-> 2592             self.figure.draw(renderer)
   2593             renderer.finalize()
   2594             file.finalize()

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\figure.py in draw(self, renderer)
   1293 
   1294             mimage._draw_list_compositing_images(
-> 1295                 renderer, self, artists, self.suppressComposite)
   1296 
   1297             renderer.close_group('figure')

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\axes\_base.py in draw(self, renderer, inframe)
   2397             renderer.stop_rasterizing()
   2398 
-> 2399         mimage._draw_list_compositing_images(renderer, self, artists)
   2400 
   2401         renderer.close_group('axes')

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    136     if not_composite or not has_images:
    137         for a in artists:
--> 138             a.draw(renderer)
    139     else:
    140         # Composite any adjacent images together

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\axis.py in draw(self, renderer, *args, **kwargs)
   1136 
   1137         for tick in ticks_to_draw:
-> 1138             tick.draw(renderer)
   1139 
   1140         # scale up the axis label box to also find the neighbors, not

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\axis.py in draw(self, renderer)
    280 
    281         if self.label1On:
--> 282             self.label1.draw(renderer)
    283         if self.label2On:
    284             self.label2.draw(renderer)

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     53                 renderer.start_filter()
     54 
---> 55             return draw(artist, renderer, *args, **kwargs)
     56         finally:
     57             if artist.get_agg_filter() is not None:

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\text.py in draw(self, renderer)
    797                     textrenderer.draw_tex(gc, x, y, clean_line,
    798                                           textobj._fontproperties, angle,
--> 799                                           mtext=mtext)
    800                 else:
    801                     textrenderer.draw_text(gc, x, y, clean_line,

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\backends\backend_pdf.py in draw_tex(self, gc, x, y, s, prop, angle, ismath, mtext)
   1942         for x1, y1, dvifont, glyph, width in page.text:
   1943             if dvifont != oldfont:
-> 1944                 pdfname = self.file.dviFontName(dvifont)
   1945                 seq += [['font', pdfname, dvifont.size]]
   1946                 oldfont = dvifont

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\backends\backend_pdf.py in dviFontName(self, dvifont)
    686             return dvi_info.pdfname
    687 
--> 688         psfont = self.texFontMap[dvifont.texname]
    689         if psfont.filename is None:
    690             raise ValueError(

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\dviread.py in __getitem__(self, texname)
    864         fn, enc = result.filename, result.encoding
    865         if fn is not None and not fn.startswith(b'/'):
--> 866             fn = find_tex_file(fn)
    867         if enc is not None and not enc.startswith(b'/'):
    868             enc = find_tex_file(result.encoding)

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\dviread.py in find_tex_file(filename, format)
   1043     # https://github.com/matplotlib/matplotlib/issues/633
   1044     pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE,
-> 1045                             stderr=subprocess.PIPE)
   1046     result = pipe.communicate()[0].rstrip()
   1047     matplotlib.verbose.report('find_tex_file result: %s' % result,

D:\Programs\Miniconda\envs\py36\lib\subprocess.py in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, encoding, errors)
    707                                 c2pread, c2pwrite,
    708                                 errread, errwrite,
--> 709                                 restore_signals, start_new_session)
    710         except:
    711             # Cleanup if the child failed starting.

D:\Programs\Miniconda\envs\py36\lib\subprocess.py in _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, unused_restore_signals, unused_start_new_session)
    969 
    970             if not isinstance(args, str):
--> 971                 args = list2cmdline(args)
    972 
    973             # Process startup details

D:\Programs\Miniconda\envs\py36\lib\subprocess.py in list2cmdline(seq)
    459             result.append(' ')
    460 
--> 461         needquote = (" " in arg) or ("\t" in arg) or not arg
    462         if needquote:
    463             result.append('"')

TypeError: a bytes-like object is required, not 'str'

Expected outcome

Saving a figure as a .pdf file.

This has worked in 2.0.2 and all the previous versions.

Matplotlib version

  • Operating system: Windows 8.1
  • Matplotlib version: 2.1.0 (installed from conda)
  • Matplotlib backend (print(matplotlib.get_backend())): module://ipykernel.pylab.backend_inline
  • Python version: 3.6.3
  • Jupyter version (if applicable): 1.0.0
@ImportanceOfBeingErnest
Copy link
Member

I tested with
Operating system: Windows 8.1, Matplotlib version: 2.1.0, Python version: 2.7.10
Matplotlib backend: module://ipykernel.pylab.backend_inline
Jupyter version: Jupyter QtConsole 4.3.0, IPython 5.3.0

and the above code generates a pdf without problem and as expected.

@anntzer
Copy link
Contributor

anntzer commented Oct 13, 2017

Almost certain it's a Py3 thing only.

@tacaswell tacaswell added this to the 2.1.1 (next bug fix release) milestone Oct 13, 2017
@tacaswell tacaswell added the Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. label Oct 13, 2017
@tacaswell
Copy link
Member

@narimiran Can you use %debug to extract the value that is causing the problem.

I am very confused why our CI did not catch this, we save pdf on both travis and appveyor.

@Kojoley
Copy link
Member

Kojoley commented Oct 13, 2017

Appveyor does not test svg and pdf currently (no builds with TEST_ALL=yes)

@tacaswell
Copy link
Member

This is probably better fixed in how we handle the file names in this section rather than patching up the subprocess call.

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\backends\backend_pdf.py in draw_tex(self, gc, x, y, s, prop, angle, ismath, mtext)
   1942         for x1, y1, dvifont, glyph, width in page.text:
   1943             if dvifont != oldfont:
-> 1944                 pdfname = self.file.dviFontName(dvifont)
   1945                 seq += [['font', pdfname, dvifont.size]]
   1946                 oldfont = dvifont

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\backends\backend_pdf.py in dviFontName(self, dvifont)
    686             return dvi_info.pdfname
    687 
--> 688         psfont = self.texFontMap[dvifont.texname]
    689         if psfont.filename is None:
    690             raise ValueError(

D:\Programs\Miniconda\envs\py36\lib\site-packages\matplotlib\dviread.py in __getitem__(self, texname)
    864         fn, enc = result.filename, result.encoding
    865         if fn is not None and not fn.startswith(b'/'):
--> 866             fn = find_tex_file(fn)
    867         if enc is not None and not enc.startswith(b'/'):
    868             enc = find_tex_file(result.encoding)

@narimiran
Copy link
Author

Can you use %debug to extract the value that is causing the problem.

I just tried to reproduce this on my Linux machine (@anntzer: it is also Python 3) and I couldn't.

I'll be back on my Windows machine on Monday, before that I can't give you more insightful answer, sorry.

@anntzer
Copy link
Contributor

anntzer commented Oct 13, 2017

@tacaswell I started by trying that (and in fact PEP383 suggests that the "correct" way to store filenames is indeed str, not bytes) but a lot of things in dviread currently assume bytes so it turns out that change is a bit complicated...

@cgohlke
Copy link
Contributor

cgohlke commented Oct 14, 2017

Fixed in #9292?

@anntzer
Copy link
Contributor

anntzer commented Oct 17, 2017

@tacaswell do you want to restore svg/pdf testing on windows? I have a patch ready that switches ghostscript to single process similarly to #8248 did for inkscape, so that may help quite a bit with the speed.

@tacaswell
Copy link
Member

@anntzer Yes, lets see how much of a time hit that is.

@tacaswell
Copy link
Member

Closed by #9292

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.

6 participants