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开发人员联系,实际上,“在未来五年内”不可能完全卸载模块。(请参阅链接)
请接受,在2.x中,Python确实不支持针对严重,根本,不可克服的技术问题的卸载模块。
在我最近一次寻找应用程序内存泄漏的过程中,我将其范围缩小到模块,即我无法 垃圾收集 已卸载的模块。使用下面列出的 任何
方法卸载模块都会在内存中保留数千个对象。换句话说-我无法在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个非垃圾对象。让我们尝试httplib
从中删除sys.modules
。
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
…
Argh!我们回到完全进口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
Python不支持卸载模块。
但是,除非您的程序随时间加载了无限数量的模块,否则这不是内存泄漏的根源。模块通常在启动时加载一次,仅此而已。您的内存泄漏很可能位于其他地方。
如果您的程序确实确实在一段时间内确实加载了无限数量的模块,那么您应该重新设计程序。;-)
问题内容: 我有一台运行时间较长的Python服务器,并且希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么? 问题答案: 你可以使用reload内置函数重新加载已导入的模块: 在Python 3中,已移至imp模块。在3.4中,不推荐使用importlib,而在中添加了。当定位到3或更高版本时,在调用reload或导入时参考相应的模块。 我认为这就是你想要的。诸如Django开发服务器
问题内容: 我有一个运行时间较长的Python服务器,并且希望能够在不重新启动服务器的情况下升级服务。最好的方法是什么? 问题答案: 您可以使用reload内置函数(仅适用于Python 3.4+)重新导入已导入的模块: 在Python 3中,已移至模块。在3.4中,imp不推荐使用,而reload在中添加了。当定位到3或更高版本时,在调用reload或导入时参考相应的模块。 我认为这就是您想要的
问题内容: 我很好奇在使用模块后是否有任何好的方法可以卸载模块。在某些情况下,我需要使用引入大量代码的模块,但是很少使用它们(例如作为管理工具),但是我犹豫使用它们,因为在此之后它们可能只会浪费内存,这可能会更好在其他地方使用。是否有任何方法可以卸载它们,无论是显式卸载还是在一段时间不使用它们时允许系统卸载它们? 问题答案: 是的,可以直接访问模块缓存: 请注意,如果您的代码中包含对您想摆脱的这些
我有一个GWT项目已经工作了几个月了。我使用的是Chrome 34.0.1847.131m的GWT开发模式,使用的是GWT 2.5.0的Eclipse EE Indigo。突然开始,加载失败,有时没有错误。经过一番调查,我发现唯一不同的是这第二行: 加载与卸载之间约150ms。这从昨天开始随机失败。在此之前,它一直运行良好。这很奇怪,我会清除我的缓存和重新启动浏览器,它工作良好的一段时间,然后它只
问题内容: 我在Mac(OS Mavericks)上安装了Python Anaconda。我想在Mac上恢复为默认版本的Python。最好的方法是什么?我应该删除目录吗?还需要其他更改吗? 目前,当我运行时,which python我会得到以下路径: 问题答案: 从文档: 要卸载,请打开终端窗口并删除整个安装目录:。您也可以编辑 和删除的森蚺目录PATH 的环境变量,并删除隐藏文件, 并可能已在主
我在Mac(OS Mavericks)上安装了Python Anaconda。我想在Mac上恢复到Python的默认版本。最好的方法是什么?我应该删除目录吗?还有其他需要修改的地方吗? 目前,当我运行我得到这个路径: 用户/用户名/anaconda/bin/python