我使用了使用matplotlib进行绘图的烧瓶框架编写了一个小的webapp。问题是,每次创建绘图时,该过程都会消耗更多内存。
我已经使用mod_wsgi部署了一个带有.wsgi文件的应用程序,看起来就像这样:
from yourapplication import app as application
当我访问创建情节的网址时,问题就开始了。该函数创建一个绘图仪对象,当它被启动时,从sqlite3数据库获取相关数据(数据由大约30个整数和相同数量的日期时间对象组成),使用matplotlib创建一个绘图并返回一个StringIO对象,然后在屏幕上显示。
这是功能的结束。可以看到整个班级here
canvas = FigureCanvas(fig)
png_output = StringIO.StringIO()
canvas.print_png(png_output)
return png_output.getvalue()
当我访问该站点时,会创建一个具有大约25MB保留内存的进程。我第一次创建一个绘图,它增长到30MB,然后每次使用绘图仪类时大约1MB。默认设置是使用5个进程消耗了太多内存(在几分钟内高达150MB,我只允许80MB)。
我对这里涉及的所有事情都很陌生(网页框架,apache,数据库)所以我没有任何感觉可能会出现问题,所以任何想法都受到高度赞赏。谢谢!
答案 0 :(得分:2)
每次调用plot_month
函数后执行此操作都可以解决泄漏问题。
import gc
gc.collect()
答案 1 :(得分:0)
发布此信息以防将来对某人有帮助。
我遇到了同样的问题,我认为axel22提供的答案并不能为我解决问题。
经过一番修补,我意识到存在两个问题:
我正在做这样的事情( INCORRECT ):
fig = util.create_figure(....)
output = io.BytesIO()
canvas = FigureCanvas(fig)
canvas.print_png(output)
但是我需要这样做(正确):
fig = util.create_figure(....)
output = io.BytesIO()
canvas = FigureCanvas(fig)
canvas.print_png(output)
# Clears the figure from memory
fig.clf()
我在代码的错误部分中调用了垃圾收集器。您需要在调用 FigureCanvas 的范围之外调用它。
此DID不起作用(错误):
import gc
def do_something():
canvas = FigureCanvas(fig)
png_output = StringIO.StringIO()
canvas.print_png(png_output)
gc.collect()
return png_output.getvalue()
do_something()
但这可行(正确):
import gc
def do_something():
canvas = FigureCanvas(fig)
png_output = StringIO.StringIO()
canvas.print_png(png_output)
return png_output.getvalue()
do_something()
gc.collect()
答案 2 :(得分:0)
当我的网站需要使用Flask循环生成一系列图形时,我遇到了与您相同的内存泄漏问题。 matplotlib的documentation在“如何在Web应用程序服务器中使用Matplotlib”部分下,实际上提到要避免使用matplotlib.pyplot
并使用matplotlib.figure.Figure
来代替避免内存泄漏。请注意,您需要Matplotlib 3.1或更高版本。
取决于构建图形的方式(CLI与OO接口)。将Pyplot类转换为Figure类非常简单。 发件人:
import matplotlib.pyplot as plt
fig = plt.figure()
收件人:
from matplotlib.figure import Figure
fig = Figure()
然后将那些无法使用的代码从CLI API替换为面向对象的API。