로 많은 그림을 만드는 스크립트에서 RuntimeWarning : 20 개 이상의 그림이 열렸다fix, ax = plt.subplots(...)
는 경고가 표시 됩니다. pyplot 인터페이스 ( matplotlib.pyplot.figure
) 를 통해 생성 된 그림 은 명시 적으로 닫힐 때까지 유지되며 너무 많은 메모리를 소비 할 수 있습니다.
그러나으로 그림을 저장 한 후으로 삭제 하기 때문에이 경고가 표시되는 이유를 이해할 수 없습니다 . 내 코드에는 아무런 문제가 없지만 한 번에 두 개 이상의 그림이 열려 있습니다. 그래도 열린 숫자가 너무 많다는 경고가 표시됩니다. 이것이 무엇을 의미합니까 / 경고를 피하는 방법은 무엇입니까?fig.savefig(...)
fig.clear(); del fig
답변
사용 .clf
또는 .cla
당신의 그림 개체에 대신 창조의 새로운 모습을. 에서 @DavidZwicker
다음 pyplot
과 같이 가져온 것으로 가정
import matplotlib.pyplot as plt
plt.cla()
axis , 즉 현재 그림에서 현재 활성 축을 지 웁니다 . 다른 축은 그대로 둡니다.
plt.clf()
모든 축으로 현재 그림 전체를 지우지 만 창을 열어두고 다른 플롯에 재사용 할 수 있습니다.
plt.close()
달리 지정하지 않으면 현재 창이 될 window를 닫습니다 . plt.close('all')
열린 숫자를 모두 닫습니다.
del fig
작동하지 않는 이유 는 pyplot
상태 머신이 그림에 대한 참조를 유지하기 때문입니다 ( ‘현재 그림’이 무엇인지 알아야 할 때와 마찬가지로). 즉 , 그림에 대한 참조를 삭제하더라도 라이브 참조가 하나 이상 있으므로 가비지 수집되지 않습니다.
@JoeKington 은이 답변에 대한 집단적 지혜에 대해 설문 조사를하고 있기 때문에 @JoeKington plt.close(fig)
은 pylab 상태 머신 ( plt._pylab_helpers.Gcf ) 에서 특정 그림 인스턴스를 제거하고 가비지 수집 될 수 있는 의견을 언급했습니다 .
답변
Hooked ‘s answer 에 대해 좀 더 자세히 설명 하겠습니다 . 내가 그 대답을 처음 읽었을 때, 나는 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()
경고를 피하려면 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 배치 후에 불만을 제기했습니다. 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()
나는 배치 내에서 그림을 재사용 할 가치가 있는지 확인하기 위해 성능을 측정 했으며이 작은 샘플 프로그램은 close()
모든 플롯 후에 방금 호출했을 때 41 초에서 49 초 (20 % 느려짐)로 느려졌습니다 .
답변
의도적으로 많은 플롯을 메모리에 유지하려고하지만 경고하지 않으려면 그림을 생성하기 전에 옵션을 업데이트 할 수 있습니다.
import matplotlib.pyplot as plt
plt.rcParams.update({'figure.max_open_warning': 0})
이렇게하면 메모리 관리 방식에 대한 변경없이 경고가 표시되지 않습니다.
답변
다음 스 니펫은 문제를 해결했습니다.
class FigureWrapper(object):
'''Frees underlying figure when it goes out of scope.
'''
def __init__(self, figure):
self._figure = figure
def __del__(self):
plt.close(self._figure)
print("Figure removed")
# .....
f, ax = plt.subplots(1, figsize=(20, 20))
_wrapped_figure = FigureWrapper(f)
ax.plot(...
plt.savefig(...
# .....
때 _wrapped_figure
범위를 벗어나 런타임은 우리의 호출 __del__()
과 방법 plt.close()
내부. _wrapped_figure
생성자 후에 예외가 발생하더라도 발생합니다 .
답변
일시적으로 경고를 표시하지 않으려는 경우에도 유용합니다.
import matplotlib.pyplot as plt
with plt.rc_context(rc={'figure.max_open_warning': 0}):
lots_of_plots()