如何在Python中打开文件后释放内存

时间:2012-09-13 22:39:07

标签: python memory file-io large-files

我在Python中打开一个3 GB的文件来读取字符串。然后我将这些数据存储在字典中。我的下一个目标是使用这个字典构建一个图表,所以我正在密切监视内存使用情况。

在我看来,Python将整个3 GB文件加载到内存中,我无法摆脱它。我的代码看起来像这样:

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,并且我使用“系统监视器”和终端中的“免费”命令监视内存使用情况。

我不明白为什么在我清除字典后Python需要这么多内存。文件是否仍存储在内存中?如果是这样,我怎么能摆脱它呢?我的操作系统没有看到释放内存的问题吗?

编辑:我在清除字典后试图强制使用gc.collect(),但无济于事。

EDIT2:我在Ubuntu 12.04.LTS上运行Python 2.7.3

编辑3:我意识到我忘了提到一些非常重要的东西。我真正的问题不在于我的操作系统没有“取回”Python使用的内存。接下来,Python似乎没有重用那个内存(它只是要求操作系统有更多的内存)。

3 个答案:

答案 0 :(得分:4)

您正在尝试使用哪个版本的python?

我在Python 2.7 / Win7上进行了测试,它按预期工作,内存已经发布。

我在这里生成像你这样的样本数据:

import random

fn = random.randint

with open('ips.txt', 'w') as f: 
    for i in xrange(9000000):
        f.write('{0}.{1}.{2}.{3} username-{4}\n'.format(
            fn(0,255),
            fn(0,255),
            fn(0,255),
            fn(0,255),
            fn(0, 9000000),
        ))

然后你的脚本。我用 defaultdict 替换了 dict ,因为抛出异常会使代码变慢:

import time
from collections import defaultdict

def read_file(filename):
    with open(filename) as data:

        accounts = defaultdict(set)

        for line in data:
            IP, username = line.split()[:2]
            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"

if __name__ == '__main__':
    read_file('ips.txt')

如您所见,内存达到1.4G然后被释放,留下36MB:

Memory usage with defaultdict

使用原始脚本我得到了相同的结果,但速度有点慢:

enter image description here

答案 1 :(得分:1)

当Python释放内存以供Python 重用以及将内存释放回操作系统时,存在差异。 Python具有用于某些类型对象的内部池,它将自行重用这些对象,但不会将其返回给操作系统。

答案 2 :(得分:0)

gc module可能很有用,尤其是collect功能。我自己从未使用它,但从文档中看,它看起来可能有用。在您运行gc.collect()之前,我会尝试运行accounts.clear()