2012-05-17 2 views
39

EDIT : matplotlib의 백엔드를 'Qt4Agg'에서 'Agg'로 명시 적으로 변경하면 오류없이 내 코드를 실행할 수 있습니다. 나는 이것이 백엔드의 버그라고 생각 하나?Matplotlib 및 Pyplot.close()가 메모리를 해제하지 않습니까? 백엔드 관련 Qt4Agg

상당히 많은 양의 데이터를 자동으로 처리하기위한 코드를 작성 중입니다. 코드는 먼저 모든 데이터 파일을 구문 분석하고 관련 비트를 모두 저장합니다. 그런 다음 필자가 필요로하는 각각의 그래프를 생성하는 데는 서로 다른 함수가 있습니다 (모두 약 25 가지가 있습니다). 그러나, 나는 어떤 종류의 메모리 오류로 계속 실행하고 Matplotlib/PyPlot이 메모리를 올바르게 해제하지 않았기 때문에 그것이라고 생각합니다.

각 plotting 함수는 pyplot.close (fig) 명령으로 끝납니다. 그래프를 저장하고 즉시보고 싶지 않으므로 이 아닌에는 pyplot.show()가 포함되어 있습니다.

인터프리터에서 플로팅 기능을 개별적으로 실행하면 문제가 발생하지 않습니다. 그러나, 각 플로팅 함수를 차례로 호출하는 별도의 함수를 만들면 "MemoryError : 경로에 메모리를 할당 할 수 없습니다"라는 오류가 발생합니다.

누구나 이런 문제가 발생 했습니까? 그것은 Matplotlib runs out of memory when plotting in a loop과 관련이있는 것 같지만 pyplot.close()는 내 문제를 해결하지 못합니다.

이 전형적인 플롯 기능 내 코드의 모습입니다 :

def TypicalPlot(self, title=None, comment=False, save=False, show=True): 

    if title is None: 
     title = self.dat.title 

    fig = plt.figure() 
    host = SubplotHost(fig, 111) 
    fig.add_subplot(host) 
    par = host.twinx() 
    host.set_xlabel("Time (hrs)") 
    host.set_ylabel("Power (W)") 
    par.set_ylabel("Temperature (C)") 
    p1, = host.plot(self.dat.timebase1, self.dat.pwr, 'b,', label="Power", 
        markevery= self.skip) 
    p2, = par.plot(self.dat.timebase2, self.dat.Temp1, 'r,', 
        label="Temp 1", markevery= self.skip) 
    p3, = par.plot(self.dat.timebase2, self.dat.Temp2, 'g,', 
        label="Temp 2", markevery= self.skip) 
    p4, = par.plot(self.dat.timebase2, self.dat.Temp3, 'm,', 
        label="Temp 3", markevery= self.skip) 
    host.axis["left"].label.set_color(p1.get_color()) 
    # par.axis["right"].label.set_color(p2.get_color()) 
    #host.legend(loc='lower left') 
    plt.title(title+" Temperature") 

    leg=host.legend(loc='lower left',fancybox=True) 
    #leg.get_frame().set_alpha(0.5) 
    frame = leg.get_frame() 
    frame.set_facecolor('0.80') 

    ### make the legend text smaller 
    for t in leg.get_texts(): 
     t.set_fontsize('small') 

    ### set the legend text color to the same color as the plots for added 
    ### readability 
    leg.get_texts()[0].set_color(p1.get_color()) 
    leg.get_texts()[1].set_color(p2.get_color()) 
    leg.get_texts()[2].set_color(p3.get_color())  
    leg.get_texts()[3].set_color(p4.get_color())   

    if show is True and save is True: 
     plt.show() 
     plt.savefig('temp.png') 
    elif show is True and save is False: 
     plt.show() 
    elif show is False and save is True: 
     plt.savefig('temp.png') 
     plt.clf() 
     plt.close(fig) 

지금 터미널

MyClass.TypicalPlot(save=True, show = False) 

에서 실행하면 그럼 난 오류를하지 않습니다. 내 플롯 기능 모두에 대해서도 마찬가지입니다.

나는이 작업을 수행 새로운 기능 한 경우 :

def saveAllPlots(self, comments = False): 

     if self.comment is None: comment = False 
     else: comment = True 
     self.TypicalPlot(save=True, show=False, comment=comment) 
     self.AnotherPlot(save=True, show=False) 
     self.AnotherPlot2(save=True, show=False) 
     self.AnotherPlot3(save=True, show=False) 
     ...etc, etc, etc 

그런 다음이 그래프의 절반 통해 실행하고 나는 "MemoryError의 : 경로에 대해 메모리를 할당 할 수 없습니다"를 얻을 수 있습니다.

+0

으로 지워졌습니까? –

+1

'plt.clf()'를 사용해 보셨습니까? – moooeeeep

+3

if/elif의 뒤에서 독립적으로 함수의 끝에 'del fig'를 추가하십시오. –

답변

1

나는 이것이 다른 그래프를 모두 통과 할 때 적절하게 해제하지 않기 때문에 아마 메모리가 부족하기 때문에이 작업을 수행하는 이유라고 생각합니다.

모든 그래프 일을 하나 개의 프로그램 대신 몇 가지 그래프를 할 각각의 약 3 정도 프로그램을 작성하지 않는 이유 :

프로그램 1 : 그래프 1-8

프로그램 2 : 그래프 9-16

프로그램 3 : 그래프 17 ~ 25

희망이 @FakeDIY하는 데 도움이 :) 내가 한 번 매우 비슷한 문제로 실행

1

. matplotlib은 각 플롯에 대한 참조를 내부적으로 유지한다고 가정합니다.별도의 세 가지 수치를 작성, 다음 코드를 감안할 때 :

import matplotlib.pyplot as plt 
import numpy as np 

# block 1 
f, ax = plt.subplots(1) 
plt.plot(np.arange(10), np.random.random(10)) 
plt.title("first") 
print 'first', sys.getrefcount(f), sys.getrefcount(ax) 

# bock 2 
f, ax = plt.subplots(1) 
plt.plot(np.arange(10), np.random.random(10)+1) 
plt.title("second") 
print 'second', sys.getrefcount(f), sys.getrefcount(ax) 

# block 3 
f, ax = plt.subplots(1) 
plt.plot(np.arange(10), np.random.random(10)+2) 
plt.title("third") 
print 'third', sys.getrefcount(f), sys.getrefcount(ax) 

plt.show() 

print 'after show', sys.getrefcount(f), sys.getrefcount(ax) 

출력 : 우리는 fax 여러 번 다시 정의하기 때문에

first 69 26 
second 69 26 
third 69 26 
after show 147 39 

이, 카운터 직관적이다. 모든 블록에서 우리는 plt을 통해 참조 할 수있는 새로운 그림을 만들었습니다. 다른 그림을 만들면 plt에 의해 접근 가능한 최상위 참조가 변경됩니다. 하지만 plt.show()에는 모든 수치를 표시 할 수있는 내부 참조가 있어야합니다. 그 참조는 영구적 인 것처럼 보이므로 인물은 GC에 의해 수집되지 않습니다.

내가 해결할 수있는 해결 방법은 플롯의 데이터를 변경하는 것이 었습니다. 돌이켜 보면 그것은 더 나은 방법은 어쨌든이었다

plt.ion() 
f, ax = plt.subplots(1) 
line = ax.plot(np.arange(10), np.random.random(10))[0] 
plt.title('first') 
plt.show() 

for i, s in [(2, 'second'), (3, 'third')]: 
    x = np.arange(10) 
    y = np.random.random(10)+i 
    line.set_data(x, y) 
    ax.set_xlim(np.min(x), np.max(x)) 
    ax.set_ylim(np.min(y), np.max(y)) 
    plt.title(s) 
    plt.draw() 
    raw_input(s) 

만 단점 당신이 열려있는 그림과 창을 유지해야합니다. 그리고 raw_input이 없으면 수치를 삭제하기 전에 프로그램을 실행하면

관련 문제