2013-04-18 35 views
2

我有一個運行循環的python腳本。在此循環中,函數DoDebugInfo被調用,每循環迭代一次。此功能基本上使用matplotlib打印一些圖片到硬盤,導出KML文件並執行一些其他計算,並且什麼都不返回python循環快速增加其內存使用

我有問題,蟒蛇,每次運行,功能DoDebugInfo吃越來越多的內存。我想一些變量正在增加每個循環的大小。

print '=== before: ' + str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1000) 
DoDebugInfo(inputs) 
print '=== after: ' + str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1000) 

輸出是:

=== before: 71598.08 
=== after: 170237.952 
=== before: 170237.952 
=== after: 255696.896 
=== before: 255696.896 
=== after: 341409.792 

正如你所看到的,在調用之前的程序有一個內存佔用,經過

我通話之前和之後添加以下行該呼叫增加,但保持穩定,直到下一次呼叫。

這是爲什麼?因爲DoDebugInfo(inputs)是一個不返回任何內容的函數,怎麼會有一些變量留在內存中?是否需要在函數結束時清除所有變量?

編輯: 的DoDebugInfo進口此功能:

def plot_line(x,y,kind,lab_x,lab_y,filename): 
    fig = plt.figure(figsize=(11,6),dpi=300) 
    ax = fig.add_subplot(111) 
    ax.grid(True,which='both') 
    #print 'plotting' 
    if type(x[0]) is datetime.datetime: 
     #print 'datetime detected' 
     ax.plot_date(matplotlib.dates.date2num(x),y,kind) 
     ax.fmt_xdata = DateFormatter('%H') 
     ax.autoscale_view() 
     fig.autofmt_xdate() 
    else: 
     #print 'no datetime' 
     ax.plot(x,y,kind) 
    xlabel = ax.set_xlabel(lab_x) 
    ax.set_ylabel(lab_y) 
    fig.savefig(filename,bbox_extra_artists=[xlabel], bbox_inches='tight') 

def plot_hist(x,Nbins,lab_x,lab_y,filename): 
    fig = plt.figure(figsize=(11,6),dpi=300) 
    ax = fig.add_subplot(111) 
    ax.grid(True,which='both') 
    ax.hist(x,Nbins) 
    xlabel = ax.set_xlabel(lab_x) 
    ax.set_ylabel(lab_y) 
    fig.savefig(filename,bbox_extra_artists=[xlabel], bbox_inches='tight') 

和情節使用類似的10個數字磁盤:

plot_line(index,alt,'-','Drive Index','Altitude in m',output_dir + 'name.png') 

如果我評論說,使用plot_line線的問題不發生,所以泄漏應該在這行代碼上。

感謝

+1

向我們展示您的'DoDebugInfo'功能。 – eumiro

+2

不返回任何內容的函數仍然可以改變全局變量,或者使用在調用之間沒有清理的可變參數。 –

+0

@eumiro我已經縮小了泄漏,請看看我在'DoDebugInfo'中使用的函數。這裏是泄漏的地方。謝謝 – otmezger

回答

4

該問題依賴於如此多的數字被創建,永遠不會關閉。不知何故,python讓他們都活着。

我增加了行

plt.close() 

每個情節我的功能plot_lineplot_hist,問題就消失了。

+1

我不知道你是否可以用'with'語句包裝那個東西? – BenDundee

+1

+1自我回答對於SO很好。 – msw

+0

@BenDundee http://docs.python.org/2/library/contextlib.html允許輕鬆創建上下文管理器 – msw

0

是否規模增長沒有約束?很少的程序(或庫)會將堆返回到它們分配的系統,即使不再使用,CPython(2.7.3)也不例外。通常的罪魁禍首是malloc,它將按需增加進程內存,將在free之後將空間返回到其自由列表,但從不重新分配它從系統請求的內存。此示例代碼有意抓住存儲器並且示出了方法中使用是有界的和有限:

import resource 

def maxrss(start, end, step=1): 
    """allocate ever larger strings and show the process rss""" 
    for exp in range(start, end, step): 
     s = '0' * (2 ** exp) 
     print '%5i: %sk' % (exp, 
      resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1000) 
    # s goes out of scope here and is freed by Python but not returned 
    # to the system 

try: 
    maxrss(1, 40, 5) 
except MemoryError: 
    print 'MemoryError' 

maxrss(1, 30, 5) 

對輸出(我的機器上)是在部分:

26: 72k 
31: 2167k 
MemoryError 
1: 2167k 
6: 2167k 
... 
26: 2170k 

其示出了解釋器失敗從系統中獲得2 ** 36字節的堆,但仍然有「手頭」的內存來填充後面的請求。正如腳本的最後一行所示,即使目前沒有使用內存,Python也可以使用該內存。

+0

它實際上在內存中不斷增長,直到我的mac難以操作並且UI幾乎被凍結。我殺了python應用程序,它釋放了4 GB的RAM。我不知道如果我讓他走得更遠,會發生什麼...... – otmezger