2012-05-15 42 views
11

我面對內存泄漏的問題使用pandas庫在python。我創建在我的課pandas.dataframe對象,我有方法,根據我的條件的變化數據幀的大小。在改變數據框大小並創建新的熊貓對象之後,我在我的類中重寫了原始pandas.dataframe。但即使在初始表格顯着減少之後,內存使用率也非常高。短例如一些代碼(不是我寫的進程管理器,看任務管理器):熊貓:這裏的內存在哪裏泄漏?

import time, string, pandas, numpy, gc 
class temp_class(): 

    def __init__(self, nrow = 1000000, ncol = 4, timetest = 5): 

     self.nrow = nrow 
     self.ncol = ncol 
     self.timetest = timetest 

    def createDataFrame(self): 

     print('Check memory before dataframe creating') 
     time.sleep(self.timetest) 
     self.df = pandas.DataFrame(numpy.random.randn(self.nrow, self.ncol), 
      index = numpy.random.randn(self.nrow), columns = list(string.letters[0:self.ncol])) 
     print('Check memory after dataFrame creating') 
     time.sleep(self.timetest) 

    def changeSize(self, from_ = 0, to_ = 100): 

     df_new = self.df[from_:to_].copy() 
     print('Check memory after changing size') 
     time.sleep(self.timetest) 

     print('Check memory after deleting initial pandas object') 
     del self.df 
     time.sleep(self.timetest) 

     print('Check memory after deleting copy of reduced pandas object') 
     del df_new 
     gc.collect() 
     time.sleep(self.timetest) 

if __name__== '__main__': 

    a = temp_class() 
    a.createDataFrame() 
    a.changeSize() 
  • 數據幀之前創建我有大約存儲器使用

  • 的15 MB創建後 - 67 MB

  • 刪除原始數據幀後 - - 35MB

  • 刪除減少表後 - 31 MB 67MB

  • 改變尺寸之後。

16 mb?

我在Windows 7(x64)機器上使用python 2.7.2(x32),pandas。 版本是0.7.3。 numpy的。 版本是1.6.1

+0

這就是Python的內存分配工作原理。可能沒有內存泄漏。 – jozzas

回答

26

幾件事情要指出:

  1. 「更改尺寸後檢查內存」,你有沒有刪除了原始數據框還,所以這將是嚴格使用更多的內存

  2. Python解釋器有點貪心操作系統內存。

我看着這個,可以向你保證,熊貓沒有泄漏記憶。我使用的是memory_profiler(http://pypi.python.org/pypi/memory_profiler)包裝:

import time, string, pandas, numpy, gc 
from memory_profiler import LineProfiler, show_results 
import memory_profiler as mprof 

prof = LineProfiler() 

@prof 
def test(nrow=1000000, ncol = 4, timetest = 5): 
    from_ = nrow // 10 
    to_ = 9 * nrow // 10 
    df = pandas.DataFrame(numpy.random.randn(nrow, ncol), 
          index = numpy.random.randn(nrow), 
          columns = list(string.letters[0:ncol])) 
    df_new = df[from_:to_].copy() 
    del df 
    del df_new 
    gc.collect() 

test() 
# for _ in xrange(10): 
#  print mprof.memory_usage() 

show_results(prof) 

而這裏的輸出

10:15 ~/tmp $ python profmem.py 
Line # Mem usage Increment Line Contents 
============================================== 
    7       @prof 
    8  28.77 MB 0.00 MB def test(nrow=1000000, ncol = 4, timetest = 5): 
    9  28.77 MB 0.00 MB  from_ = nrow // 10 
    10  28.77 MB 0.00 MB  to_ = 9 * nrow // 10 
    11  59.19 MB 30.42 MB  df = pandas.DataFrame(numpy.random.randn(nrow, ncol), 
    12  66.77 MB 7.58 MB        index = numpy.random.randn(nrow), 
    13  90.46 MB 23.70 MB        columns = list(string.letters[0:ncol])) 
    14 114.96 MB 24.49 MB  df_new = df[from_:to_].copy() 
    15 114.96 MB 0.00 MB  del df 
    16  90.54 MB -24.42 MB  del df_new 
    17  52.39 MB -38.15 MB  gc.collect() 

所以事實上,有更多的內存使用比我們開始時。但它泄漏了嗎?

for _ in xrange(20): 
    test() 
    print mprof.memory_usage() 

輸出:

10:19 ~/tmp $ python profmem.py 
[52.3984375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59375] 
[122.59765625] 
[122.59765625] 
[122.59765625] 

因此,實際上什麼不見了上是Python的過程是抱着一種給它被使用,以避免繼續請求更多的內存什麼的存儲池(和然後釋放它)從主機操作系統。我不知道背後的所有技術細節,但至少發生了什麼。