警告太多开放的数字
在一个脚本中,我创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%)。