【问题标题】:Matplotlib errors result in a memory leak. How can I free up that memory?Matplotlib 错误会导致内存泄漏。我怎样才能释放那个内存?
【发布时间】:2011-10-30 20:12:09
【问题描述】:

我正在运行一个包含 matplotlib 并允许用户指定图形轴的 django 应用程序。这可能会导致“溢出错误:超出 Agg 复杂度”

当这种情况发生时,多达 100MB 的 RAM 会被占用。通常我使用fig.gcf()plot.close()gc.collect() 释放内存,但与错误相关的内存似乎与绘图对象无关。

有谁知道我怎样才能释放那段记忆?

谢谢。

这里有一些代码会出现 Agg 复杂性错误。

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np      
import gc

a = np.arange(1000000)
b = np.random.randn(1000000)

fig = plt.figure(num=1, dpi=100, facecolor='w', edgecolor='w')
fig.set_size_inches(10,7)
ax = fig.add_subplot(111)
ax.plot(a, b)

fig.savefig('yourdesktop/random.png')   # code gives me an error here

fig.clf()    # normally I use these lines to release the memory
plt.close()
del a, b
gc.collect()

【问题讨论】:

    标签: python memory-leaks matplotlib


    【解决方案1】:

    我在这里找到 http://www.mail-archive.com/matplotlib-users@lists.sourceforge.net/msg11809.html ,它给出了一个有趣的答案,可能会有所帮助

    尝试替换:

    import matplotlib.pyplot as plt
    fig = plt.figure()
    

    from matplotlib import figure
    fig = figure.Figure()
    

    【讨论】:

    • 此解决方案适用于使用 for 循环保存多个绘图时出现的错误“MemoryError: In RendererAgg: Out of memory”
    【解决方案2】:

    我假设您至少可以运行您发布的代码一次。该问题仅在多次运行发布的代码后才会出现。对吗?

    如果是这样,则以下内容在没有真正确定问题根源的情况下避免了该问题。 也许这是一件坏事,但这在紧要关头起作用:只需使用multiprocessing 在单独的进程中运行内存密集型代码。您不必担心fig.clf()plt.close()del a,bgc.collect()。进程结束时,所有内存都会被释放。

    import matplotlib
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt
    import numpy as np      
    
    import multiprocessing as mp
    
    def worker():
        N=1000000
        a = np.arange(N)
        b = np.random.randn(N)
    
        fig = plt.figure(num=1, dpi=100, facecolor='w', edgecolor='w')
        fig.set_size_inches(10,7)
        ax = fig.add_subplot(111)
        ax.plot(a, b)
    
        fig.savefig('/tmp/random.png')   # code gives me an error here
    
    if __name__=='__main__':
        proc=mp.Process(target=worker)
        proc.daemon=True
        proc.start()
        proc.join()
    

    您也不必proc.join()join 将阻塞主进程,直到 worker 完成。如果省略join,则主进程将继续,worker 进程在后台运行。

    【讨论】:

    • 我发布的代码第一次通过失败。创建它是为了重新创建用户在 y 轴上放大太多以获取高采样率数据的特殊情况。如果绘图看起来像一片蓝色而没有显示任何白色背景,则代码失败。但是,您的解决方案看起来像是管理内存的更好方法。我是新手,我不完全理解if __name__ == '__main__': 块发生了什么。我将尝试将此添加到我的代码中。你能给我指出一个解释发生了什么的资源吗?或者你能提供一个快速的解释。谢谢。
    • @sequoia:在这种情况下,也许你需要限制用户,所以在任何情况下用户都不能请求绘制 1e6 个点。 if __name__... 块不是必需的,除非您在 Windows 上。我很乐意解释你的任何具体问题,但我认为在这种情况下,一切都比我能解释得更好here
    • 谢谢,这是一个有用的链接。我将使用您的实现。并采纳您的建议来限制用户请求的范围。
    • 哇!我无法相信这种解决方法为我解决了类似的问题。当然,这不是解决根本问题的方法。但这是一种很好的技术,可以在紧急情况下使用。
    猜你喜欢
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多