为什么python列表切片赋值会占用内存?

6 投票
2 回答
1035 浏览
提问于 2025-04-16 02:03

我在一个Python项目中遇到了内存泄漏的问题,花了很多时间在上面。经过一些分析,我把问题简化成了一个小例子。现在我好像知道解决办法了,但我不太明白为什么

import random

def main():
    d = {}
    used_keys = []
    n = 0
    while True:
        # choose a key unique enough among used previously
        key = random.randint(0, 2 ** 60)
        d[key] = 1234 # the value doesn't matter
        used_keys.append(key)
        n += 1
        if n % 1000 == 0:
            # clean up every 1000 iterations
            print 'thousand'
            for key in used_keys:
                del d[key]
                used_keys[:] = []
                #used_keys = []

if __name__ == '__main__':
    main()

我的想法是把一些值存储在字典d中,并把使用过的键存到一个列表里,这样我就可以不时地清理这个字典。

这个程序的变体会不断占用内存,却不释放出来。如果我使用示例中注释掉的另一种方法来“清空”used_keys,那么一切就正常了:内存使用量保持在一个稳定的水平。

这是为什么呢?

在CPython和多个Linux系统上测试过。

2 个回答

0

为什么像这样的代码不管用呢?

from itertools import count
import uuid

def main():
    d = {}
    for n in count(1):
        # choose a key unique enough among used previously
        key = uuid.uuid1()
        d[key] = 1234 # the value doesn't matter
        if n % 1000 == 0:
            # clean up every 1000 iterations
            print 'thousand'
            d.clear()

if __name__ == '__main__':
    main()
5

原因在于,当前的方法并没有从字典中删除键(实际上只删除了一个)。这是因为你在循环中清空了 used_keys 列表,导致循环过早结束。

而第二种(被注释掉的)方法之所以有效,是因为你给 used_keys 赋了一个新值,这样循环就能顺利完成。

看看这两者之间的区别:

>>> a=[1,2,3]
>>> for x in a:
...    print x
...    a=[]
...
1
2
3

>>> a=[1,2,3]
>>> for x in a:
...    print x
...    a[:] = []
...
1
>>>

撰写回答