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

Python 包含字典键的内部列表即使在从字典中删除键后也不会释放内存,python,python-2.7,memory-management,dictionary,python-internals,Python,Python 2.7,Memory Management,Dictionary,Python Internals,我在用python 2.7编写的python脚本中使用字典 当我使用pympler运行脚本查找内存泄漏时,我发现列表对象的大小正在难以置信地增加 这些列表包含这些字典的键。这些列表是否在python字典的构建实现中? pympler的输出如下: types | # objects | total size ============================ | =========== | ============

我在用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

你的问题是测试不好造成的

在循环中,您可以执行以下操作:

all_objects = muppy.get_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)) 

现在,在循环中,您只需调用
summary()
,并确保没有任何您不想要的局部变量。

您的问题是测试不好造成的

在循环中,您可以执行以下操作:

all_objects = muppy.get_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)) 

现在,在循环中,您只需调用
summary()
,并确保不存在任何您不想要的局部变量。

您的标题包含一个断言,您的问题显示为一个假设。你测试过这个吗?你能提供一个其他人可以用来重现这种行为的最小示例吗?“该列表包含所用字典的键,我认为这是字典的内部实现。”不;字典的内部实现没有任何列表。查看它们的实际工作方式。我用示例代码编辑了我的问题。我测试了代码。代码和PYMPPLER输出也显示在Meanwhile中:从dict中删除项不一定会缩小dict的哈希表,在大多数实现中,这样做要么永远不会,要么很少。如果您有一个dict比其暂时的最大大小小得多,并且确实需要压缩它,最简单的方法就是复制一份。那么,当我在脚本中没有使用列表时,为什么类型“list”的大小会增加?列表包含字典的键。您的标题包含一个断言,您的问题将其作为假设显示。你测试过这个吗?你能提供一个其他人可以用来重现这种行为的最小示例吗?“该列表包含所用字典的键,我认为这是字典的内部实现。”不;字典的内部实现没有任何列表。查看它们的实际工作方式。我用示例代码编辑了我的问题。我测试了代码。代码和PYMPPLER输出也显示在Meanwhile中:从dict中删除项不一定会缩小dict的哈希表,在大多数实现中,这样做要么永远不会,要么很少。如果您有一个dict,它变得比其暂时的最大大小小得多,并且确实需要压缩它,最简单的方法就是只制作一个副本。那么,当我在脚本中没有使用列表时,为什么类型“list”的大小在增加?列表包含字典的键。