使用Python动态在网页上展示matplotlib图像
这个问题在这里以类似的方式被问过 这里,但答案对我来说太复杂了(我对python和网页开发都是新手),所以我希望能有更简单的方法,或者能用不同的方式解释一下。
我想用matplotlib生成一张图片,并且不想先把文件写到服务器上。我的代码可能有点傻,但大致是这样的:
import cgi
import matplotlib.pyplot as pyplot
import cStringIO #I think I will need this but not sure how to use
...a bunch of matplotlib stuff happens....
pyplot.savefig('test.png')
print "Content-type: text/html\n"
print """<html><body>
...a bunch of text and html here...
<img src="test.png"></img>
...more text and html...
</body></html>
"""
我觉得我应该用一个叫做cstringIO的对象,而不是直接用pyplot.savefig('test.png'),然后做类似这样的事情:
mybuffer=cStringIO.StringIO()
pyplot.savefig(mybuffer, format="png")
但从那之后我就有点迷茫了。我看到的所有例子(比如 http://lost-theory.org/python/dynamicimg.html)都涉及到做一些像这样的事情:
print "Content-type: image/png\n"
而我不太明白怎么把这些和我已经输出的HTML结合起来。
6 个回答
9
我在使用Python3时,发现这个方法对我很有效:
buf = io.BytesIO()
plt.savefig(buf, format='png')
image_base64 = base64.b64encode(buf.getvalue()).decode('utf-8').replace('\n', '')
buf.close()
13
上面的回答有点过时了——这里是我在Python3+中获取图像数据原始字节的方法。
import matplotlib.pyplot as plt
from io import BytesIO
fig = plt.figure()
plt.plot(range(10))
figdata = BytesIO()
fig.savefig(figdata, format='png')
正如其他回答提到的,你现在需要设置一个'Content-Type'头为'image/png',然后输出字节。
根据你使用的网络服务器,代码可能会有所不同。我使用Tornado作为我的网络服务器,下面是实现这个功能的代码:
self.set_header('Content-Type', 'image/png')
self.write(figdata.getvalue())
21
你应该这样做:
- 首先写入一个 cStringIO 对象
- 然后写入 HTTP 头信息
- 接着把 cStringIO 的内容写到标准输出(stdout)
这样,如果在 savefig
过程中出现错误,你仍然可以返回其他内容,甚至是另一个头信息。有些错误不会提前被发现,比如文本问题、图片尺寸过大等。
你需要告诉 savefig
输出应该写到哪里。你可以这样做:
format = "png"
sio = cStringIO.StringIO()
pyplot.savefig(sio, format=format)
print "Content-Type: image/%s\n" % format
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) # Needed this on windows, IIS
sys.stdout.write(sio.getvalue())
如果你想把图片嵌入到 HTML 中:
print "Content-Type: text/html\n"
print """<html><body>
...a bunch of text and html here...
<img src="data:image/png;base64,%s"/>
...more text and html...
</body></html>""" % sio.getvalue().encode("base64").strip()