包含字典键的内部列表即使从字典中删除键后也不会释放内存

时间:2015-04-16 11:08:27

标签: python python-2.7 memory-management dictionary python-internals

我在用python 2.7编写的python脚本中使用字典。

当我使用 pympler 运行我的脚本来查找内存泄漏时,我发现列表对象的大小正在不断增加。

这些列表包含这些词典的键。这些列表是python词典的构建实现吗?

pympler的输出如下:

                         types |   # objects |   total size
  ============================ | =========== | ============
                    list |       99221 |    106.53 MB
                     str |      105530 |      6.06 MB
                    dict |         602 |    940.48 KB
                    code |        1918 |    239.75 KB
                     int |       10043 |    235.38 KB
      wrapper_descriptor |        1120 |     87.50 KB
                    type |          87 |     76.80 KB
 builtin_function_or_method |         719 |     50.55 KB
       method_descriptor |         601 |     42.26 KB
                     set |         132 |     33.41 KB
                 weakref |         372 |     31.97 KB
                   tuple |         364 |     26.24 KB
     <class 'abc.ABCMeta |          20 |     17.66 KB
       member_descriptor |         233 |     16.38 KB
     function (__init__) |         114 |     13.36 KB

列表的大小正在增加,scipt的RES内存也在增加? 该列表包含所使用的字典的键,我认为它是字典的内部实现。 密钥是否作为列表存储在内存中?如何管理内存泄漏?

以下是上述输出的代码:

         from pympler import tracker
         from pympler import summary
         from pympler import muppy
         import types
         while(1):
          d={}
          for i in range(1000,1100):
             d[i]=1
          for i in range(1000,1050):
            del d[i]
          all_objects = muppy.get_objects()
          sum1 = summary.summarize(all_objects)
          summary.print_(sum1) 
          type = muppy.filter(all_objects, Type=types.ListType)
          print 'length :%s'%(len(type)) 

1 个答案:

答案 0 :(得分:4)

你的问题是一个很难测试的东西。

在你的循环中,你这样做:

all_objects = muppy.get_objects()

您永远不会删除all_objects,因此在您拨打get_objects时,所有对象的上一个列表仍然是实时对象。当然,当您将新列表分配给all_objects时,您会删除该引用,但为时已晚;现在,所有对象的新列表都引用了所有对象的旧列表。

这实际上是人们使用各种进程内存调试工具的常见问题 - 很容易最终保留工具的工件并最终调试这些工件。

确保您不会意外地执行此类操作的一个好方法是将您的muppy代码分解为函数:

def summarize():
    all_objects = muppy.get_objects()
    sum1 = summary.summarize(all_objects)
    summary.print_(sum1) 
    type = muppy.filter(all_objects, Type=types.ListType)
    print 'length :%s'%(len(type)) 

现在,在循环中,您只需致电summarize(),并确保您无法找到任何您不想要的局部变量。