我正在用Python打开一个3gb的文件来读取字符串。然后我把这些数据储存在字典里。我的下一个目标是使用这个字典构建一个图,这样我就可以密切监视内存使用情况。
在我看来,Python将整个3gb文件加载到内存中,而我无法摆脱它。我的代码是这样的:
with open(filename) as data:
accounts = dict()
for line in data:
username = line.split()[1]
IP = line.split()[0]
try:
accounts[username].add(IP)
except KeyError:
accounts[username] = set()
accounts[username].add(IP)
print "The accounts will be deleted from memory in 5 seconds"
time.sleep(5)
accounts.clear()
print "The accounts have been deleted from memory"
time.sleep(5)
print "End of script"
最后几行是为了监视内存使用情况。 该脚本使用的内存超过3 GB。清除字典可以释放大约300 MB的空间。当脚本结束时,剩余的内存被释放。
我在使用Ubuntu,我在终端中同时使用“System Monitor”和“free”命令来监控内存使用情况。
我不明白的是,为什么Python在我清除字典之后需要这么多内存。文件是否仍存储在内存中?如果是的话,我怎样才能摆脱它呢?我的操作系统看不到释放的内存有问题吗?
编辑:我试图在清除字典后强制执行gc.collect(),但没有效果。
EDIT2:我在Ubuntu 12.04.LTS上运行Python 2.7.3
伊迪丝3:我意识到我忘了提一些很重要的事情。我真正的问题不是我的操作系统没有“找回”Python使用的内存。稍后,Python似乎不会重用该内存(它只是要求操作系统有更多的内存)。
Python释放内存以供Python重用与释放内存回OS之间存在差异。Python为某些类型的对象提供了内部池,它将重用这些对象本身,但不会将其返回给OS。
这对我来说也毫无意义,我想弄清楚这是怎么发生的。(我也这么认为!)我把它复制到了我的机器上——不过用的是一个小文件。
我在这里看到两个离散的问题
我根本不懂Python内部的知识,所以我只是做了大量的web搜索。所有这些都可能完全偏离目标。(我几乎不再发展,在过去的几年里一直在科技行业工作)
懒线阅读
我环顾四周发现了这个帖子-
http://www.peterbe.com/plog/blogitem-040312-1
这是一个更早版本的python,但这句话引起了我的共鸣:
然后我看到了这个,同样古老的,effbot帖子:
http://effbot.org/zone/readline-performance.htm
关键是:
而这个:
查看用于xreadlines[http://docs.python.org/library/stdtypes.html?highlight=readline#file.xreadlines]的pythons文档:
这让我觉得也许有人在说粗话。
所以如果我们看看readlines[http://docs.python.org/library/stdtypes.html?highlight=readline#file.readlines]。。。
好像就是这样。
然而,readline看起来像我们想要的http://docs.python.org/library/stdtypes.html?highlight=readline#file.readline
所以我试着把它切换到readline,进程从来没有超过40MB(之前它已经增长到200MB,日志文件的大小)
我的猜测是,我们并不是真的在偷懒地阅读带有
for x in data
结构的文件——尽管所有的文档和stackoverflow注释都表明我们是。readline()
对我来说消耗的内存少得多,realdlines
消耗的内存量与for line in data
差不多释放记忆
在释放内存方面,我对Python的内部结构不太熟悉,但我回想起来,在使用mod_perl时。。。如果我打开一个500MB的文件,那么这个apache子文件就会增长到这个大小。如果我释放了内存,它将只在那个子内存中是空闲的——垃圾收集的内存在进程退出之前不会返回给操作系统。
所以我仔细研究了一下这个想法,发现了一些链接,暗示这可能正在发生:
http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm
那有点旧了,后来我在python中发现了一堆随机(可接受的)补丁,这些补丁表明行为发生了变化,现在可以将内存返回到os(截至2005年,大多数补丁都已提交并得到了批准)。
然后我找到了这篇文章http://objectmix.com/python/17293-python-memory-handling.html——并注意到注释4
如果“for line in data:”构造实际上是包装
readlines
,而不是包装readline
,那么这可能与它有关?也许拥有一个3GB的对象不是问题,而是拥有数百万个30k的对象。你在尝试哪个版本的python?
我在Python2.7/Win7上做了一个测试,果然成功了,内存被释放了。
在这里,我生成与您类似的示例数据:
然后是你的剧本。我用defaultdict替换了dict,因为抛出异常会使代码变慢:
如您所见,内存达到1.4G,然后释放,剩下36MB:
使用您的原始脚本,我得到了相同的结果,但速度稍慢:
相关问题 更多 >
编程相关推荐