Home > Mobile >  AttributeError: 'str' object has no attribute 'draw_path'
AttributeError: 'str' object has no attribute 'draw_path'

Time:02-27

I'm converting an antiquated Matplotlib script that's written for Python 2.7 and Matplotlib 1.3.1 (legacy MacOS Python implementation) to Python 3 and Matplotlib 3.5.1. Unfortunately, I can't provide a reproducible example as the code is proprietary (I've tried to reproduce the error from scratch, but haven't been able to.) so apologies for the lack on an MVCE.

I'm getting the following error when I send the plot to savefig on an area chart:

Traceback (most recent call last):
  File "chart_area.py", line 323, in <module>
    chart_tools.save(logger=LOG)
  File "/Users/Dave/PycharmProjects/matplotlib/chart_tools.py", line 1053, in save
    plt.savefig(
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/pyplot.py", line 859, in savefig
    res = fig.savefig(*args, **kwargs)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/figure.py", line 2311, in savefig
    self.canvas.print_figure(fname, **kwargs)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/backend_bases.py", line 2210, in print_figure
    result = print_method(
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/backend_bases.py", line 1639, in wrapper
    return func(*args, **kwargs)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/backends/backend_agg.py", line 509, in print_png
    FigureCanvasAgg.draw(self)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/backends/backend_agg.py", line 407, in draw
    self.figure.draw(self.renderer)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/figure.py", line 1862, in draw
    self.patch.draw(renderer)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/patches.py", line 587, in draw
    draw_path(tpath, affine,
  File "/Users/Dave/Library/Python/3.8/lib/python/site-packages/matplotlib/patheffects.py", line 100, in draw_path
    path_effect.draw_path(self._renderer, gc, tpath, affine,
AttributeError: 'str' object has no attribute 'draw_path'

The savefig call is:

plt.savefig(f"{payload['p_dict']['chartPath']}{payload['p_dict']['fileName']}", **payload['k_dict']['k_plot_fig'])

The save path is (type = string) and the kwargs are dirt simple (type = dict):

{'bbox_extra_artists': None, 'bbox_inches': None, 'format': None, 'frameon': None, 'orientation': None, 'pad_inches': None, 'papertype': None, 'transparent': True}

The relevant lines from matplotlib's draw_path.py are:

def draw_path(self, gc, tpath, affine, rgbFace=None):             # 98
    for path_effect in self._path_effects:                        # 99
        path_effect.draw_path(self._renderer, gc, tpath, affine,  # 100
                              rgbFace)

I have no idea whatsoever why the path_effect object is coming across as a string.

The same project has a text-only chart which uses the same savefig method call and doesn't produce the error. As far as I can tell, there are no animations in the entire project. I've tried both with and without kwargs and get the same error. A possibility might be something in plt.rcParams or a style sheet but I suspect (e.g. don't know) that there is something being passed to an axes or subplot that's the culprit. I suppose it's also possible that the stacktrace is a red herring and theres a bytes/strings problem somewhere. I'm stumped.

UPDATE 1:

I modified patheffects.py to inspect the payload that was coming through the draw_path() method:

object type value
self._path_effects list ['[]']
path_effect string '[]'

I tried converting the path_effect object to a list object using literal_eval, but then got the following traceback:

AttributeError: 'list' object has no attribute 'draw_path'

I'm beginning to suspect that there might be a bug in the version of matplotlib I'm using 3.5.1

CodePudding user response:

Turns out the source of the error is a style sheet entry. matplotlib expects lists to be passed without [ or ] (and be comma separated). When matplotlib encounters [] it doesn't interpret it as a list. An empty list would be represented as:

path.effects:

and not what I was working with:

path.effects: []

A properly formatted list parm would be:

some.thing: 1, 2, 3, 4, 5
  • Related