and*_*s-h 128 python matplotlib python-3.x
在我创建许多数字的脚本中fix, ax = plt.subplots(...),我收到警告RuntimeWarning:已打开超过20个数字.通过pyplot接口(matplotlib.pyplot.figure)创建的数字将保留,直到明确关闭,并可能消耗太多内存.
但是,我不明白为什么我得到这个警告,因为保存图后fig.savefig(...),我删除它fig.clear(); del fig.我的代码中没有任何一点,我一次打开多个数字.尽管如此,我还是得到了关于太多公开数字的警告.这是什么意思/如何避免收到警告?
Hoo*_*ked 160
使用.clf或.cla在图形对象上而不是创建新图形.来自@DavidZwicker
假设您已导入pyplot为
import matplotlib.pyplot as plt
Run Code Online (Sandbox Code Playgroud)
plt.cla()清除轴,即当前图中当前活动的轴.它使其他轴保持不变.
plt.clf()用它的所有轴清除整个当前图形,但是打开窗口,这样它就可以重新用于其他图形.
plt.close()如果没有另外指定,则关闭一个窗口,该窗口将是当前窗口.plt.close('all')将关闭所有未结数字.
del fig不起作用的原因是pyplot状态机保持对图形的引用(如果它将知道"当前图形"是什么必须的话).这意味着即使您删除了您的参考图,也至少有一个实时参考,因此它永远不会被垃圾收集.
由于我在这里对集体智慧进行了轮询,因此@JoeKington在评论中提到plt.close(fig)将从pylab状态机(plt._pylab_helpers.Gcf)中删除特定的图形实例并允许它被垃圾收集.
Don*_*kby 23
这里有更多细节来扩展Hooked的答案.当我第一次读到这个答案时,我错过了调用的指令clf() 而不是创建一个新的数字.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()
Run Code Online (Sandbox Code Playgroud)
为了避免警告,我必须将呼叫拉到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()
Run Code Online (Sandbox Code Playgroud)
如果您要批量生成绘图,则可能必须同时使用cla()和close().我遇到了一个问题,批次可能有20多个地块没有抱怨,但它会在20批后抱怨.我通过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()
Run Code Online (Sandbox Code Playgroud)
我测量了性能以确定是否值得重复使用批量中的数字,并且当我close()在每个绘图之后调用时,这个小样本程序从41s减慢到49s(慢20%).
mig*_*ile 13
如果您打算故意在内存中保留许多图表,但不希望对其进行警告,则可以在生成数据之前更新选项.
import matplotlib.pyplot as plt
plt.rcParams.update({'figure.max_open_warning': 0})
Run Code Online (Sandbox Code Playgroud)
这样可以防止在不改变内存管理方式的情况下发出警告.
| 归档时间: |
|
| 查看次数: |
72191 次 |
| 最近记录: |