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

Internal List containing Dictionary Keys does not deallocating memory even after removing keys from the dictionary

我在用 python 2.7.

编写的 python 脚本中使用字典

当我 运行 我的脚本使用 pympler 查找内存泄漏时,我发现列表对象的大小正在难以置信地增加。

并且这些列表包含 dictionary.Is 这些列表在 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

list的大小在增加,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)) 

你的问题是测试不当造成的。

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

all_objects = muppy.get_objects()

您永远不会删除 all_objects,因此在您调用 get_objects 时,之前所有对象的列表仍然是活动对象。当然,当您将新列表分配给 all_objects 时,您会删除该引用,但为时已晚;所有对象的新列表现在引用了所有对象的旧列表。

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

确保您不会不小心做这种事情的一个好方法是将您的代码分解成一个函数:

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(),并确保您不会有任何您不想要的局部变量。