警告太多开放的数字

在一个脚本中,我创build了许多数字fix, ax = plt.subplots(...) ,我得到警告RuntimeWarning:超过20个数字已打开。 通过pyplot接口( matplotlib.pyplot.figure )创build的数字将保留,直到显式closures并可能消耗太多的内存。

然而,我不明白为什么我会得到这个警告,因为用fig.savefig(...)保存graphics后,我用fig.clear(); del fig删除它fig.clear(); del fig fig.clear(); del fig 。 在我的代码中,我一次只能打开一个以上的数字。 不过,我得到了太多开放数字的警告。 这是什么意思/我怎样才能避免得到警告?

在你的graphics对象上使用.clf.cla ,而不是创build一个新的graphics。 从@DavidZwicker

假设你已经input了pyplot

 import matplotlib.pyplot as plt 

plt.cla()清除一个轴 ,即当前活动轴。 它保持其他轴不变。

plt.clf()清除整个当前graphics的所有坐标轴,但会将窗口打开,以便可以重新用于其他graphics。

如果没有指定, plt.close()closures一个窗口 ,它将成为当前窗口。 plt.close('all')将closures所有打开的数字。

del fig不起作用的原因是pyplot状态机保持对这个数字的引用(因为它必须知道“当前数字”是什么)。 这意味着,即使你删除你的参考数字,至less有一个现场参考,因此它永远不会被垃圾收集。

由于我在这里回答了这个问题的集体智慧,@JoeKington在评论中提到, plt.close(fig)会从pylab状态机( plt._pylab_helpers.Gcf )中删除一个特定的数字实例并允许它垃圾收集。

这里有更多的细节来展开Hooked的回答 。 当我第一次读到这个答案时,我错过了调用clf() 而不是创build一个新数字的指令。 如果你自己去创造另一个数字, clf()本身并不起作用。

以下是导致警告的简单示例:

 from matplotlib import pyplot as plt, patches import os def main(): path = 'figures' for i in range(21): _fig, ax = plt.subplots() x = range(3*i) y = [n*n for n in x] ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10)) plt.step(x, y, linewidth=2, where='mid') figname = 'fig_{}.png'.format(i) dest = os.path.join(path, figname) plt.savefig(dest) # write image to file plt.clf() print('Done.') main() 

为了避免这种警告,我必须把呼叫拉到循环外的subplots() 。 为了不断看到矩形,我需要将clf()切换到cla() 。 清除轴而不移除轴本身。

 from matplotlib import pyplot as plt, patches import os def main(): path = 'figures' _fig, ax = plt.subplots() for i in range(21): x = range(3*i) y = [n*n for n in x] ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10)) plt.step(x, y, linewidth=2, where='mid') figname = 'fig_{}.png'.format(i) dest = os.path.join(path, figname) plt.savefig(dest) # write image to file plt.cla() print('Done.') main() 

如果您正在批量生成绘图,则可能必须同时使用cla()close() 。 我碰到一个问题,一批可以有20多个地块没有抱怨,但是会在20个批次后投诉。 我通过在每个plot之后使用cla()来解决这个问题,并且在每个批处理之后使用close()

 from matplotlib import pyplot as plt, patches import os def main(): for i in range(21): print('Batch {}'.format(i)) make_plots('figures') print('Done.') def make_plots(path): fig, ax = plt.subplots() for i in range(21): x = range(3 * i) y = [n * n for n in x] ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10)) plt.step(x, y, linewidth=2, where='mid') figname = 'fig_{}.png'.format(i) dest = os.path.join(path, figname) plt.savefig(dest) # write image to file plt.cla() plt.close(fig) main() 

我测量了性能,看看是否值得在一批中重复使用这个数字,而当我在每个plot之后调用close()时,这个小示例程序从41s减慢到49s(减慢了20%)。