python – 用Flask提供Matplotlib图像的习语有什么区别?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 用Flask提供Matplotlib图像的习语有什么区别?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5064字,纯文字阅读大概需要8分钟。
内容图文
Web搜索引出了几个简单的(未记录的)示例(以及良好的answers here左右)如何使用Flask动态提供Matplotlib数字;但是有这些的特征,它们之间的差异让我感到困惑.
Some使用低级IO并返回元组
io = StringIO.StringIO()
plt.savefig(io, format='png')
io.seek(0)
data = io.read()
return data, 200, {'Content-type': 'image/png'}
而several others使用不同的IO API并返回响应
io = StringIO.StringIO()
canvas = FigureCanvas(fig)
canvas.print_png(io)
response = make_response(io.getvalue())
response.mimetype = 'image/png' # or response.headers['Content-Type'] = 'image/png'
return response
然而others采用不同的方法来编码和构建返回值
io = StringIO.StringIO()
fig.savefig(io, format='png')
data = io.getvalue().encode('base64')
return html.format(data)
所有这些似乎都有效;但我想知道它们共享的方法是否有特征,或者它们之间的差异是否具有非明显的后果(例如性能或对不同场景的适用性).
第一,
> StringIO扮演的角色是什么;它是准备服务图像(任何类型)的唯一方法吗?
在我受保护的Python生活中,我以前从未见过它,并且不清楚为什么它似乎是服务器a(二进制文件)文件过程的必需部分.
其次,我想知道这些例子用来包装他们的反应的不同方法;特别
>使用seek plus read与getvalue有什么关系,或者这些基本上是相同的;
>什么决定了返回的方法之间的选择:元组与html.format与响应(使用make_response);最后
>为什么有些方法明确设置Content-type,而其他方法设置编码(‘base64’)?
这些方法中的任何一种都被认为是“最佳”或最新的惯用(或至少是Pythonic)方法吗?
解决方法:
what is the role played by StringIO; is it the only way to prepare to
serve an image (of any kind)?
首先,不,这不是唯一的方法. “经典”方式是涉及文件系统:
>让matplotlib创建一个情节.
>将相应的图像数据持久保存到文件系统中的文件中(包括上下文切换到调用系统调用的内核,如write()).
>再次读取此文件的内容(允许内核通过read()读取文件系统).
>通过定义良好的数据编码的HTTP响应以及正确设置的标头,将内容提供给客户端.
步骤(3)和(4)涉及文件系统交互.也就是说,内核实际上与硬件组件对话.这需要时间(对于传统的hrad驱动器,只需几个字节写入光盘可能需要几毫秒,因为访问时间很长).现在,问题是:您是否需要将图像数据保存到磁盘?如果答案为“否”,则可以通过将图像数据保留在Web应用程序进程的内存中来跳过与文件系统的整个交互并节省一些时间.这就是StringIO的优点:
StringIO是Python中非常通用的工具,它提供类似文件的对象,而实际数据永远不会委托给内核,以便将其写入文件系统或从文件系统中读取.它保存在记忆中.这就是StringIO对象也被称为内存中文件的原因.
关键是plt.savefig()想要一个对象作为第一个参数,它看起来像一个实际代表文件系统中真实文件的对象. StringIO提供了这样一个对象,但是 – 在引擎盖下 – 将数据写入当前进程的堆中的缓冲区,并在请求时再次从那里读取它.
通过StringIO读取/写入小部分数据需要纳秒或微秒,而与文件系统的交互通常是数量级较慢的数量级.
现在,不要误会我的意思:通常,文件系统足够快,并且操作系统有自己的技术来尽可能快地进行文件系统交互.真正的问题是,如前所述:您是否需要保留图像数据?如果您稍后不关心访问此图像数据,则不要涉及文件系统.这就是你展示的三个片段的创建者所决定的.
出于性能原因替换与StringIO的实际文件系统交互可能是一个非常有效的决策.但是,在您的Web应用程序中肯定存在其他瓶颈.例如,使用StringIO可以减少请求 – 响应延迟,比如说5 ms.但考虑到100毫秒的网络延迟,这实际上是否重要?此外,请记住,一个严肃的Web应用程序最好不要被发送大文件内容所困扰 – 这些更好地服务于一个完善的Web服务器,它也可以使用sendfile()系统调用.在这种情况下,让matplotlib将文件写入文件系统然后告诉您的Web服务器(通过X-Sendfile头)完成剩下的工作可能会再次提高性能.因此,性能是一个复杂的话题可能不是最强的论据.但只有你知道你的要求!
is there any significance to the use of seek plus read, vs. getvalue,
or do these do essentially the same thing
基本上是一样的.不会产生概念上的差异,也不会产生(重大)性能差异.
what governs the choice among approaches for what is returned: a tuple
vs. html.format vs. a Response (with make_response); and, finally
没有明确的答案.有很多方法可以将数据传输到客户端.没有“正确”的方法,只是好或坏.哪种方法最强烈取决于Web框架.使用Flask,make_response()是创建响应对象的规范方法. html.format()可能有一些我不知道的优点 – 你需要自己阅读!但是,请继续阅读,我认为Flask内置了一种方法,非常适合您的场景.
why do some approaches set the Content-type explicitly, while others
set the encoding (to ‘base64’)?
有正确和不正确的方法通过HTTP将文件发送到浏览器.通常,HTTP响应应包含某些标头(另请参见What HTTP response headers are required).只是为了您的理解,您可能想了解这些细节.当然,二进制数据需要使用客户端理解的编码进行编码,并且必须在响应头中阐明编码.此外,正确的HTTP响应应包含MIME类型(内容类型).你提出的方法似乎并没有真正掌控一方或另一方(没有冒犯,快速和肮脏的例子往往更多地关注一件事而不是另一件事).
我认为你真的应该使用Flask的send_file方法来处理一些重要的事情.这种方法有几个参数.我会通过mimetype显式定义MIME类型.第一个参数可以是类文件对象,因此StringIO对象可以正常工作.但是,在这种情况下,您需要先执行搜索(0):
Make sure that the file pointer is positioned at the start of data to
send before calling send_file().
以下两种方法在语义上都很优雅(在我看来),并且应该适当注意编码文件内容和设置HTTP响应头:
from flask import send_file
1)
f = StringIO.StringIO()
plt.savefig(f, format='png', dpi=300)
f.seek(0)
send_file(f, mimetype='image/png')
2)
plt.savefig('image.png', dpi=300)
send_file('image.png', mimetype='image/png')
在第二种情况下,如果配置正确,您的网络服务器(例如nginx)可以为您传输文件.
内容总结
以上是互联网集市为您收集整理的python – 用Flask提供Matplotlib图像的习语有什么区别?全部内容,希望文章能够帮你解决python – 用Flask提供Matplotlib图像的习语有什么区别?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。