В сценарии, в котором я создаю много фигур fix, ax = plt.subplots(...)
, я получаю предупреждение RuntimeWarning: открыто более 20 фигур. Рисунки, созданные с помощью интерфейса pyplot ( matplotlib.pyplot.figure
), сохраняются до явного закрытия и могут занимать слишком много памяти.
Однако я не понимаю, почему я получаю это предупреждение, потому что после сохранения рисунка fig.savefig(...)
я удаляю его с помощью fig.clear(); del fig
. Ни в одной точке моего кода не было открыто более одной фигуры одновременно. Тем не менее, я получаю предупреждение о слишком большом количестве открытых фигур. Что это значит / как я могу избежать предупреждения?
python
python-3.x
matplotlib
андреас-ч
источник
источник
plt
вообще обойти стороной. Например, stackoverflow.com/a/16337909/325565 (Не включать один из моих собственных ответов, но это тот, который я мог бы найти быстрее всего ...)Ответы:
Используйте
.clf
или.cla
на вашем объекте фигуры вместо создания новой фигуры. От @DavidZwickerПредполагая, что вы импортировали
pyplot
какplt.cla()
очищает ось , то есть текущую активную ось на текущем рисунке. Это оставляет другие оси нетронутыми.plt.clf()
очищает всю текущую фигуру со всеми ее осями, но оставляет окно открытым, чтобы его можно было использовать для других графиков.plt.close()
закрывает окно , которое будет текущим, если не указано иное.plt.close('all')
закроет все открытые фигуры.Причина, по которой
del fig
это не работает, заключается в том, чтоpyplot
конечный автомат сохраняет ссылку на фигуру (как это должно быть, если он собирается знать, что такое «текущая фигура»). Это означает, что даже если вы удалите свою ссылку на фигуру, есть хотя бы один живой реф, поэтому он никогда не будет собирать мусор.Поскольку здесь я опрашиваю коллективный разум для этого ответа, @JoeKington упоминает в комментариях, что
plt.close(fig)
удалит конкретный экземпляр фигуры из конечного автомата pylab ( plt._pylab_helpers.Gcf ) и разрешит его сборку мусора.источник
clf
дляfigure
класса, но нетclose
. Почему наdel fig
самом деле не закрыть и не удалить фигуру?close
которое не будет работать на объекте рисунка, называйте это какplt.close()
, вместоfig.clf()
.del fig
это не работает, заключается в том, что предоставление ему__del__
метода (который в основном вызываетсяplt.close(fig)
) может привести к возникновению циклических ссылок в данном конкретном случае, аfig
наличие__del__
метода приведет к тому, что другие вещи не будут собираться мусором , (Или это мое смутное воспоминание, во всяком случае.) В любом случае, это, конечно, немного раздражает, но вы должны звонитьplt.close(fig)
вместоdel fig
. Кстати, matplotlib действительно может использовать контекстный менеджер для этого ...plt.close(fig)
он удалит конкретный экземпляр фигуры из конечного автомата pylab (plt._pylab_helpers.Gcf
) и позволит собирать мусор.plt
немного беспорядок, и есть мысли о том, как это сделать заново. Менеджер контекста интригует .... См. Github.com/matplotlib/matplotlib/pull/2736 , github.com/matplotlib/matplotlib/pull/2624Вот немного подробнее, чтобы расширить ответ Хукеда . Когда я впервые прочитал этот ответ, я пропустил инструкцию для вызова
clf()
вместо создания новой фигуры .clf()
сам по себе не поможет, если вы тогда пойдете и создадите другую фигуру.Вот тривиальный пример, который вызывает предупреждение:
Чтобы избежать предупреждения, я должен вытащить вызов за
subplots()
пределы цикла. Чтобы продолжать видеть прямоугольники, мне нужно переключитьсяclf()
наcla()
. Это очищает ось без удаления самой оси.Если вы генерируете графики в пакетном режиме, вам, возможно, придется использовать оба варианта
cla()
иclose()
. Я столкнулся с проблемой, когда партия может иметь более 20 участков без жалоб, но она будет жаловаться после 20 партий. Я исправил это, используяcla()
после каждого графика иclose()
после каждой партии.Я измерил производительность, чтобы увидеть, стоит ли повторно использовать цифру в пакете, и эта небольшая программа-пример замедлилась с 41 до 49 с (на 20% медленнее), когда я только что звонил
close()
после каждого графика.источник
Если вы намереваетесь сознательно хранить много графиков в памяти, но не хотите, чтобы об этом предупреждали, вы можете обновить свои параметры до создания цифр.
Это предотвратит выдачу предупреждения без каких-либо изменений в способе управления памятью.
источник
Следующий фрагмент решил проблему для меня:
Когда
_wrapped_figure
выходит из области видимости, среда выполнения вызывает наш__del__()
метод сplt.close()
inside. Это происходит, даже если исключение срабатывает после_wrapped_figure
конструктора.источник
Это также полезно, если вы хотите временно отключить предупреждение:
источник