2012-05-17 11 views
39

संपादित करें: यदि मैं 'Qt4Agg' से matgotlib के लिए बैकएंड को 'एजीजी' में बदलता हूं तो मैं बिना किसी त्रुटि के अपने कोड को चलाने में सक्षम हूं। मुझे लगता है कि यह बैकएंड में एक बग है?Matplotlib और Pyplot.close() स्मृति जारी नहीं कर रहे हैं? - बैकएंड संबंधित Qt4Agg

मैं स्वचालित रूप से डेटा की एक बड़ी मात्रा को संसाधित करने के लिए कुछ कोड लिख रहा हूं। सबसे पहले कोड मेरी डेटा फ़ाइलों को पार करता है और सभी प्रासंगिक बिट्स स्टोर करता है। मेरे पास आवश्यक प्रत्येक ग्राफ के उत्पादन के लिए अलग-अलग फ़ंक्शन हैं (सभी में लगभग 25 हैं)। हालांकि, मैं किसी प्रकार की मेमोरी त्रुटि में चल रहा हूं और मुझे लगता है कि ऐसा इसलिए है क्योंकि Matplotlib/PyPlot स्मृति को सही ढंग से जारी नहीं कर रहा है।

प्रत्येक साजिश रचने समारोह एक pyplot.close (छवि) कमांड के साथ समाप्त होता है और के बाद से मैं सिर्फ रेखांकन को बचाने के लिए और उन पर नहीं लग रहे चाहते तुरंत वे नहीं एक pyplot.show शामिल करते हैं()।

यदि मैं एक दुभाषिया में व्यक्तिगत रूप से साजिश कार्यों को चलाता हूं तो मुझे कोई समस्या नहीं होती है। हालांकि, अगर मैं एक अलग फ़ंक्शन करता हूं जो प्रत्येक प्लॉटिंग फ़ंक्शन को बदले में कॉल करता है तो मैं "मेमोरी एरर: पथ के लिए स्मृति आवंटित नहीं कर सका" में चला जाता हूं।

क्या कोई इस तरह की समस्या से आया है? यह Matplotlib runs out of memory when plotting in a loop से संबंधित प्रतीत होता है लेकिन pyplot.close() मेरी समस्या को ठीक नहीं करता है। मैं अब एक टर्मिनल

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

में चलाते हैं तो मैं किसी भी त्रुटि नहीं मिलता है

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) 

:

यह एक ठेठ साजिश समारोह मेरी कोड में कैसा दिखता है। मेरे सभी साजिश कार्यों के लिए भी यही सच है।

अगर मैं एक नया कार्य जो ऐसा करता है:

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

फ़ंक्शन के अंत में 'del fig' जोड़ने का प्रयास करें, उसके बाद/elif के आजादी के बाद। –

उत्तर

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) 

आउटपुट:

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

यह काउंटर सहज है, क्योंकि हम f और ax कई बार नए सिरे से परिभाषित। प्रत्येक ब्लॉक के साथ, हमने एक नया आंकड़ा बनाया, जिसे plt के माध्यम से संदर्भित किया जा सकता है। एक और आंकड़ा बनाना plt द्वारा सबसे ऊपर संदर्भों को सुलभ करता है। लेकिन कुछ आंतरिक संदर्भ होना चाहिए, जो सभी आंकड़े दिखाने के लिए plt.show() की अनुमति देता है। वे संदर्भ लगातार प्रतीत होते हैं और इस प्रकार आंकड़े जीसी द्वारा एकत्र नहीं किए जाएंगे।

मैं जिस कामकाज के साथ बस गया, वह साजिश का डेटा बदल रहा था। हिंडसाइट में यह एक बेहतर तरीका था:

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 के बिना कार्यक्रम केवल

संबंधित मुद्दे