0

I am trying to plot some values and pass them to a Flask template. I tried using this method: How to render and return plot to view in flask?

Unfortunately I get this error.

TypeError: string argument expected, got 'bytes'

I got through to the template when changed the img type to BytesIO, but still it wouldn't show the plot.

I am dead in the water here, can anybody help?

Here is my plot.py

@app.route('/plot', methods=['POST']) # I use POST because I will introduce user specified data
def plot():
if request.method == 'POST':

    img = io.BytesIO()
    x = [1,2,3,6,7]
    y = [4,6,7,9,10]
    plt.plot(x, y)
    plt.savefig(img, format='png')
    plt.savefig("../xxxx.png") # this works just fine
    img.seek(0)
    plot_url = base64.b64encode(img.getvalue())
    return render_template('plot.html', plot_url=plot_url)

And this is plot.html:

{% extends "layout.html" %}
{% block body %}


<img src="data:image/png;base64, {{ plot_url }}" width="20" height="20" alt="graph">
{% endblock %}
Community
  • 1
  • 1
DCzo
  • 141
  • 2
  • 14
  • 1
    Have you looked at: http://stackoverflow.com/questions/6479100/python-stringio-replacement-that-works-with-bytes-instead-of-strings – Jeremy May 20 '17 at 22:52
  • Thank you, yes I saw this post but it did not solve my problem. Changing the type to BytesIO solves the incompatibility, but I still don't see the image in the browser. I seems to me that the problem might lie in the encoding, because when i tried to savefig to a file it worked just fine. – DCzo May 20 '17 at 23:08
  • Could you post some of the code in question? I could answer better if I saw where the error was arising from. – Jeremy May 20 '17 at 23:09
  • I edited my initial post – DCzo May 20 '17 at 23:20

1 Answers1

3

What Python version are you using? On Python 3.x base64.b64encode() returns bytes object and that's why it probably fails. You need to decode it into a string before passing it to Flask. Also, you should URL-escape your base64-encoded string since you're printing it inside of your HTML, something like:

import urllib.parse

# ...

img = io.BytesIO()  # create the buffer
plt.savefig(img, format='png')  # save figure to the buffer
img.seek(0)  # rewind your buffer
plot_data = urllib.parse.quote(base64.b64encode(img.read()).decode()) # base64 encode & URL-escape
return render_template('plot.html', plot_url=plot_data)
zwer
  • 24,943
  • 3
  • 48
  • 66