【发布时间】:2011-03-07 13:19:53
【问题描述】:
TL/DR:
import gc, sys
print len(gc.get_objects()) # 4073 objects in memory
# Attempt to unload the module
import httplib
del sys.modules["httplib"]
httplib = None
gc.collect()
print len(gc.get_objects()) # 6745 objects in memory
更新 我已经就这个问题联系了 Python 开发人员,确实是 not going to be possible to unload a module 完全“在未来五年内”。 (见链接)
请接受 Python 在 2.x 中确实不支持针对严重、基本、不可克服的技术问题卸载模块。
在我最近在我的应用程序中寻找 memleak 期间,我已将其范围缩小到模块,即我无法垃圾收集卸载的模块。使用下面列出的 any 方法来卸载模块会在内存中留下数千个对象。换句话说 - 我无法在 Python 中卸载模块......
剩下的问题是尝试以某种方式对模块进行垃圾收集。
让我们试试吧:
import gc
import sys
sm = sys.modules.copy() # httplib, which we'll try to unload isn't yet
# in sys.modules, so, this isn't the source of problem
print len(gc.get_objects()) # 4074 objects in memory
让我们保存sys.modules 的副本以便稍后尝试恢复它。
所以,这是一个基线 4074 个对象。理想情况下,我们应该以某种方式回到这一点。
让我们导入一个模块:
import httplib
print len(gc.get_objects()) # 7063 objects in memory
我们最多有 7K 个非垃圾对象。
让我们尝试从sys.modules 中删除httplib。
sys.modules.pop('httplib')
gc.collect()
print len(gc.get_objects()) # 7063 objects in memory
好吧,那没用。嗯,但__main__ 中没有引用吗?哦对了:
del httplib
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
万岁,下降 300 个物体。不过,没有雪茄,那是 4000 多件原始物品。
让我们尝试从副本中恢复sys.modules。
sys.modules = sm
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
嗯,那是没有意义的,没有改变.. 也许如果我们消灭全局变量...
globals().clear()
import gc # we need this since gc was in globals() too
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
本地人?
locals().clear()
import gc # we need this since gc was in globals() too
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
什么.. 如果我们 imported exec 内部的一个模块会怎样?
local_dict = {}
exec 'import httplib' in local_dict
del local_dict
gc.collect()
print len(gc.get_objects()) # back to 7063 objects in memory
现在,这不公平,它导入到__main__,为什么?它不应该离开local_dict...啊!我们回到完全导入的httplib。
也许我们用一个虚拟对象替换它?
from types import ModuleType
import sys
print len(gc.get_objects()) # 7064 objects in memory
血腥.....!!
sys.modules['httplib'] = ModuleType('httplib')
print len(gc.get_objects()) # 7066 objects in memory
去死模块,去死!!
import httplib
for attr in dir(httplib):
setattr(httplib, attr, None)
gc.collect()
print len(gc.get_objects()) # 6749 objects in memory
好吧,经过所有尝试,最好的结果是从起点开始 +2675(几乎 +50%)...这只是来自一个模块...内部甚至没有任何大的东西...
好的,现在说真的,我的错误在哪里? 如何卸载模块并清除其所有内容? 还是 Python 的模块是一个巨大的内存泄漏?
完整源代码更易于复制:http://gist.github.com/450606
【问题讨论】:
-
1.你有没有一一检查过,剩下的对象到底是什么? 2.ou 正在尝试使用“python”模块进行测试。您是否尝试过使用您创建的幼稚大模块的相同方法?一个不引用自身外部任何东西的模块?
标签: python memory-leaks