【问题标题】:How to clear memory completely of all matplotlib plots如何完全清除所有matplotlib图的内存
【发布时间】:2015-04-29 17:01:23
【问题描述】:

我有一个数据分析模块,其中包含多次调用matplotlib.pyplot API 以在每次运行中生成多达 30 个数字的函数。这些数字在生成后会立即写入磁盘,因此我需要从内存中清除它们。

目前,在每个函数结束时,我都会这样做:

import matplotlib.pyplot as plt

plt.clf()

但是,我不太确定这个语句是否真的可以清除内存。我特别担心,因为我发现每次运行我的模块进行调试时,我的可用内存空间都在不断减少。

每次将绘图写入磁盘后,我需要做什么才能真正清除内存?

【问题讨论】:

标签: python memory matplotlib


【解决方案1】:

特别是当您运行多个进程或线程时,最好定义您的图形变量并直接使用它:

from matplotlib import pyplot as plt

f = plt.figure()
f.clear()
plt.close(f)

无论如何,必须结合使用 plt.clear() 和 plt.close()

更新(2021/01/21)

如果您使用 MacOS 系统及其默认后端(称为“MacOSX”),则这不起作用(至少在 Big Sur 中)。我找到的唯一解决方案是切换到其他知名后端,例如 TkAgg、Cairo 等。要做到这一点,只需键入:

import matplotlib
matplotlib.use('TkAgg') # Your favorite interactive or non-interactive backend

【讨论】:

    【解决方案2】:

    经过一周的试验,我得到了解决方案!希望它可以帮助你。 附上我的演示。

    import matplotlib.pyplot as plt
    import numpy as np
    
    A = np.arange(1,5)
    B = A**2
    
    cnt=0
    while(1):  
        cnt = cnt+1
        print("########### test %d ###########" % cnt)
    
        # here is the trick: 
        # set the figure a 'num' to prevent from re-malloc of a figure in the next loop 
        # and set "clear=True" to make the figure clear
        # I never use plt.close() to kill the figure, because I found it doesn't work.
        # Only one figure is allocated, which can be self-released when the program quits.
        # Before: 6000 times calling of plt.figure() ~ about 1.6GB of memory leak
        # Now: the memory keeps in a stable level
        fig = plt.figure(num=1, clear=True)
        ax = fig.add_subplot()
    
        # alternatively use an other function in one line
        # fig, ax = plt.subplots(num=1,clear=True)
    
        ax.plot(A,B)
        ax.plot(B,A)
    
        # Here add the functions you need 
        # plt.show()
        fig.savefig('%d.png' % cnt)
    

    【讨论】:

    • 可以作证,就像一个魅力。请注意,如果将 plt.close(f) 与上述解决方案结合使用,仍然会发生内存泄漏。
    【解决方案3】:

    我有一个数据分析模块,其中包含多个调用 Matplotlib pyplot API 的函数

    您可以编辑调用 matplotlib 的函数吗?我遇到了同样的问题,我尝试了以下命令,但都没有奏效。

    plt.close(fig)
    fig.clf()
    gc.collect()
    %reset_selective -f fig
    

    然后一个技巧对我有用,而不是每次都创建一个新图形,而是将相同的 fig 对象传递给函数,这解决了我的问题。

    例如使用,

    fig = plt.figure()
    for i in range(100):
        plt.plot(x,y)
    

    而不是,

    for i in range(100):
        fig = plt.figure()
        plt.plot(x,y)
    

    【讨论】:

      【解决方案4】:

      这更像是一个测试套件,而不是问题的答案。 在这里我展示了截至 2021 年 12 月,没有提供的解决方案实际上会清除内存。

      我们需要以下库:

      import os
      import psutil 
      import numpy
      import matplotlib
      import matplotlib.pyplot
      

      我创建了一个应该清除所有 matplotlib 内存的函数:

      def MatplotlibClearMemory():
          #usedbackend = matplotlib.get_backend()
          #matplotlib.use('Cairo')
          allfignums = matplotlib.pyplot.get_fignums()
          for i in allfignums:
              fig = matplotlib.pyplot.figure(i)
              fig.clear()
              matplotlib.pyplot.close( fig )
          #matplotlib.use(usedbackend) 
      

      我制作了一个创建 100 个图形的脚本,然后尝试将它们全部从内存中删除:

      #Use TkAgg backend because it works better for some reason:
      matplotlib.use('TkAgg')
      
      #Create fake data for our figures:
      x = numpy.arange(1000)
      
      #Get system process information for printing memory usage:
      process = psutil.Process(os.getpid())
      
      #Check memory usage before we create figures:
      print('BeforeFigures: ', process.memory_info().rss)  # in bytes
      
      #Make 100 figures, and check memory usage:
      for n in range(100):
          matplotlib.pyplot.figure()
          matplotlib.pyplot.plot(x, x)
      print('AfterFigures:  ', process.memory_info().rss)  # in bytes
      
      #Clear the all the figures and check memory usage:
      MatplotlibClearMemory( )
      print('AfterDeletion: ', process.memory_info().rss)  # in bytes
      

      输出剩余内存:

      >>> BeforeFigures: 76083200
      >>> AfterFigures:  556888064
      >>> AfterDeletion: 335499264
      

      分配的内存不到一半被清除(如果使用标准后端则更少)。此堆栈溢出页面上唯一可行的解​​决方案是避免同时在内存中放置多个图形。

      【讨论】:

      • 当我创建更多图形或让它们容纳更多数据时,这似乎会逐渐接近清除一半的内存。
      【解决方案5】:

      迟到的答案,但这对我有用。我有一个很长的顺序代码生成许多绘图,并且在进程结束时它总是会吃掉所有的 RAM。 我没有在每个图完成后调用 fig.close(),而是简单地重新定义了 plt.figure 函数,如下所示,以便它自动完成:

      import matplotlib.pyplot as plt
      import copy
      try:
         # if script it run multiple times, only redefine once
         plt.old_figure
      except:
        # matplotlib is imported for the first time --> redefine
        plt.old_figure = copy.deepcopy(plt.figure)
        def newfig(*args):
          plt.show()
          plt.close("all")
        return plt.old_figure(*args)
        plt.figure = newfig
      

      我很清楚这不是一个好的解决方案,但是它简单、快速并且对我有用!也许有一种方法可以装饰 plt.figure 而不是重新定义它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-14
        • 1970-01-01
        • 1970-01-01
        • 2017-12-05
        • 2017-02-09
        • 2015-09-09
        • 2017-09-18
        • 2011-01-28
        相关资源
        最近更新 更多