0

I am using Python 3 and Flask with Matplotlib and numpy.

I wish to load pages that generate many plots which are embedded into the page.

I have tried following suggestions made in other places, such as this stackoverflow question and this github post.

However, when I try to implement anything of the kind I get all kinds of IO related errors. Usually of the form:

TypeError: string argument expected, got 'bytes'

and is generated inside of:

site-packages/matplotlib/backends/backend_agg.py

specifically the print_png function

I understand python3 no longer has a StringIO import, which is what is producing the error, and instead we are to import io and call it with io.StringIO() - at least that is what I understand we are to do, however, I can't seem to get any of the examples I have found to work.

The structure of my example is almost identical to that of the stackoverflow question listed above. The page generates as does the image route. It is only the image generation itself that fails.

I am happy to try a different strategy if someone has a better idea. To be clear, I need to generate plots - some times many (100+ on any single page and hundreds of pages) - from data in a database and display them on a webpage. I was hoping to avoid generating files that I then have to clean up given the large number of files I will probably generate and the fact they may change as data in the DB changes.

3
  • 1
    This error means that you have to decode() from bytes to string using 'utf-8' or other encodings. Problem is because in Python2 there was no difference between str and bytes. And Python3 use unicode as str. Commented Oct 10, 2016 at 2:35
  • Yes, but where, the error is inside the matplotlib package. My access to it is in the savefig(img) call and I can't decode that to a string. I assume the problem lies in the line img = io.StringIO() that precedes it but I do not know how else to create an object to save the figure and pass back to the rendering engine. Commented Oct 10, 2016 at 3:49
  • It is the img = io.StringIO() line it should be img = io.BytesIO() Commented Oct 10, 2016 at 4:05

1 Answer 1

2

The code taken from this stackoverflow question which is used in the above question contains the following:

    import StringIO
    ...
    fig = draw_polygons(cropzonekey)
    img = StringIO()
    fig.savefig(img)

As poitned out by @furas, Python3 treats bytes and strings differently to Python2. In many Python 2 examples StringIO is used for cases like the above but in Python3 it will not work. Therefore, we need modify the above like this:

    import io
    ...
    fig = draw_polygons(cropzonekey)
    img = BytesIO()
    fig.savefig(img)

Which appears to work.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.