Gregory Miller
Gregory Miller

Reputation: 131

Error saving matplotlib figures to pdf: 'str' object has no attribute 'decode'

I have the following script to generate a figure with matplotlib:

 # -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
import math

from matplotlib import rc
rc('font',**{'family':'serif'})
rc('text', usetex=True)
rc('text.latex',unicode=True)
rc('text.latex',preamble=r'\usepackage[utf8]{inputenc}')
rc('text.latex',preamble=r'\usepackage[russian]{babel}')

def figsize(wcm,hcm): plt.figure(figsize=(wcm/2.54,hcm/2.54))
figsize(13,9)

x = np.linspace(0,2*math.pi,100)
y = np.sin(x)
plt.plot(x,y,'-')
plt.xlabel(u"Ось абсцисс")
plt.show()

It works fine and the figure is rendered correctly. But when I'm trying to save it to pdf, I get the following error:

Traceback (most recent call last):
  File "C:\Path\rus pics\___test_rus.py", line 22, in <module>
    plt.savefig(u"c:/fig.pdf")
  File "C:\Python35\lib\site-packages\matplotlib\pyplot.py", line 688, in savefig
    res = fig.savefig(*args, **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\figure.py", line 1565, in savefig
    self.canvas.print_figure(*args, **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\backend_bases.py", line 2232, in print_figure
    **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\backends\backend_pdf.py", line 2536, in print_pdf
    self.figure.draw(renderer)
  File "C:\Python35\lib\site-packages\matplotlib\artist.py", line 61, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\figure.py", line 1159, in draw
    func(*args)
  File "C:\Python35\lib\site-packages\matplotlib\artist.py", line 61, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\axes\_base.py", line 2324, in draw
    a.draw(renderer)
  File "C:\Python35\lib\site-packages\matplotlib\artist.py", line 61, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\axis.py", line 1120, in draw
    self.label.draw(renderer)
  File "C:\Python35\lib\site-packages\matplotlib\artist.py", line 61, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Python35\lib\site-packages\matplotlib\text.py", line 792, in draw
    mtext=mtext)
  File "C:\Python35\lib\site-packages\matplotlib\backends\backend_pdf.py", line 1866, in draw_tex
    psfont = self.tex_font_mapping(dvifont.texname)
  File "C:\Python35\lib\site-packages\matplotlib\backends\backend_pdf.py", line 1568, in tex_font_mapping
    return self.tex_font_map[texfont]
  File "C:\Python35\lib\site-packages\matplotlib\dviread.py", line 701, in __getitem__
    result = self._font[texname.decode('ascii')]
AttributeError: 'str' object has no attribute 'decode'

The error arises only if I use cyrillic letters in labels.

Upvotes: 1

Views: 2015

Answers (2)

Gregory Miller
Gregory Miller

Reputation: 131

The problem was solved by installing cm-super package with missing larm1200 font. Matplotlib developers, thanks for help!

Upvotes: 2

Gregory Miller
Gregory Miller

Reputation: 131

Using XeLaTex turned out to be a nice workaround. It has its own issues (for example, XeLaTex fails on figures with fill_between), but still it allowed to get cyrillic letters in labels.

# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division, print_function, unicode_literals)

import matplotlib as mpl
mpl.use("pgf")
pgf_with_custom_preamble = {
    "font.family": "serif", # use serif/main font for text elements
    "text.usetex": True,    # use inline math for ticks
    "pgf.rcfonts": False,   # don't setup fonts from rc parameters
    "pgf.preamble": [
         "\\usepackage{units}",         # load additional packages
         "\\usepackage{metalogo}",
         "\\usepackage{unicode-math}",  # unicode math setup
         r"\setmathfont{xits-math.otf}",
         r"\setmainfont{DejaVu Serif}", # serif font via preamble
         ]
}
mpl.rcParams.update(pgf_with_custom_preamble)
import matplotlib.pyplot as plt
import numpy as np
import math

def figsize(wcm,hcm): plt.figure(figsize=(wcm/2.54,hcm/2.54))
figsize(13,9)

x = np.linspace(0,2*math.pi,100)
y = np.sin(x)
plt.plot(x,y,'-')
plt.xlabel(u"Ось абсцисс")
#plt.show()

plt.savefig(u"d:/fig.pdf")

Upvotes: 1

Related Questions