gpt4 book ai didi

python - 使用Flask提供Matplotlib图像的成语之间有什么区别?

转载 作者:太空宇宙 更新时间:2023-11-03 14:20:53 25 4
gpt4 key购买 nike

一个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并返回a Response
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(binary?)文件。
其次,我想知道这些例子在包装它们的响应时采用的不同方法;特别是
使用 seekplus readgetvalue有什么意义吗,或者做这些基本上是一样的事情;
决定返回内容的方法选择的是什么:元组vs.cc>vs.a html.format(with Response);最后
为什么有些方法显式地设置 make_response,而另一些方法则设置编码(base64)?
这些方法中有没有一种被认为是“最好的”或者是目前最惯用的(或者至少是蟒蛇式的)方法?

最佳答案

斯金吉奥扮演的角色是什么?这是准备
为(任何类型的)形象服务?
首先,不,这不是唯一的办法“经典的”方法是使用文件系统:
让matplotlib创建绘图。
持久地将相应的图像数据保存到文件系统中的一个文件中(这涉及到上下文切换到调用系统调用的内核,如write())。
再次读取此文件的内容(这使内核可以通过read()为您读取文件系统)。
在具有定义良好的数据编码和正确设置头的http响应中,向客户端提供内容。
步骤(3)和(4)涉及文件系统交互也就是说,内核实际上与硬件组件进行对话。这需要时间(对于传统的hrad驱动器,仅向磁盘写入几个字节可能需要几毫秒,因为访问时间很长)。现在,问题是:您需要将图像数据持久化到磁盘吗?如果答案是“否”,那么您可以跳过与文件系统的整个交互,将图像数据保存在web应用程序进程的内存中,从而节省一些时间。这就是StringIO的好处:
StringIO是python中一个非常通用的工具,它提供类似文件的对象,而实际的数据从来没有委托给内核将其写入文件系统或从文件系统读取。它被保存在记忆中这就是为什么StringIO对象也被称为内存文件的原因。
关键是plt.savefig()希望有一个对象作为第一个参数,它看起来像一个实际代表文件系统中真实文件的对象StringIO提供了这样一个对象,但是——在幕后——将数据写入当前进程堆中的缓冲区,并在请求时从那里再次读取数据。
通过StringIO读取/写入小部分数据需要纳秒或微秒,而与文件系统的交互通常要慢几个数量级。
现在,请不要误会:通常,文件系统足够快,而且操作系统有自己的技术,可以使文件系统交互尽可能快。真正的问题是,如前所述:是否需要持久化图像数据?如果您不想在以后的某个时候访问此图像数据,则不要涉及文件系统。这是你展示的三个片段的创造者决定的。
出于性能原因,用StringIO替换真正的文件系统交互可能是一个非常有效的决定然而,在您的web应用程序中肯定还有其他瓶颈例如,使用StringIO可以减少请求-响应延迟5毫秒,但考虑到100毫秒的网络延迟,这是否真的很重要另外,请记住,一个严肃的web应用程序最好不要为发送大文件内容而烦恼——这些文件内容最好由一个建立良好的web服务器提供,该服务器还可以使用sendfile()系统调用在这种情况下,让matplotlib将文件写入文件系统,然后告诉您的web服务器(通过X-Sendfile头)执行其余操作可能会更好。所以,性能是一个复杂的话题可能不是最有力的论据。但只有你知道你的要求!
使用seek plus read和getvalue有什么意义吗?
或者它们做了本质上相同的事情
本质上是一样的不会产生概念上的差异,也不会产生(显著的)性能差异。
决定返回内容的方法选择的是什么:元组
对html.format对a response(带有make_response);最后
没有明确的答案向客户机获取数据的方法有很多。没有“正确”的方法,只是好坏。哪种方法最好,这在很大程度上取决于web框架。对于Flask,make_response()是创建响应对象的标准方法html.format()可能有一些我不知道的优点——你需要自己读一下!但是,继续读下去,我认为有一种方法内置在烧瓶里,非常适合你的场景。
为什么有些方法显式地设置内容类型,而另一些方法
是否将编码设置为“base64”?
通过http向浏览器发送文件有正确和不正确的方法。通常,http响应应该包含某些头(另请参见What HTTP response headers are required)。为了你的理解,你可能想看看这些细节。当然,二进制数据需要用客户机能够理解的编码进行编码,并且必须在响应头中澄清编码此外,正确的HTTP响应应该包含MIME类型(内容类型)你所提出的方法似乎并不能真正控制其中的一个或另一个(没有冒犯,快速和肮脏的例子往往更多地关注一件事而不是另一件事)。
我认为你真的应该用烧瓶法来处理一些重要的事情这个方法有几个参数我将通过mimetype显式定义mime类型。第一个参数可以是类似文件的对象,因此stringio对象可以正常工作。但是,在这种情况下,您需要在执行以下操作之前执行seek(0)
确保文件指针位于
在调用send_file()之前发送。
以下两种方法在语义上很优雅(在我看来),应该适当地注意对文件内容进行编码和设置http响应头:

from flask import send_file 

(一)
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')

在第二种情况下,如果配置正确,您的web服务器(例如nginx)可以为您传输文件。

关于python - 使用Flask提供Matplotlib图像的成语之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28091129/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com