【发布时间】:2010-11-05 08:23:22
【问题描述】:
我创建了一些 python 代码,它在循环中创建一个对象,并且在每次迭代中都用一个相同类型的新对象覆盖这个对象。这样做了 10.000 次,Python 每秒占用 7mb 内存,直到我的 3gb RAM 被使用。有谁知道从内存中删除对象的方法?
【问题讨论】:
标签: python optimization memory-management garbage-collection
我创建了一些 python 代码,它在循环中创建一个对象,并且在每次迭代中都用一个相同类型的新对象覆盖这个对象。这样做了 10.000 次,Python 每秒占用 7mb 内存,直到我的 3gb RAM 被使用。有谁知道从内存中删除对象的方法?
【问题讨论】:
标签: python optimization memory-management garbage-collection
我认为这是循环引用(尽管问题并未明确说明此信息。)
解决此问题的一种方法是手动调用垃圾回收。当您手动运行垃圾收集器时,它也会清除循环引用的对象。
import gc
for i in xrange(10000):
j = myObj()
processObj(j)
#assuming count reference is not zero but still
#object won't remain usable after the iteration
if !(i%100):
gc.collect()
这里不要太频繁地运行垃圾收集器,因为它有自己的开销,例如如果你在每个循环中运行垃圾收集器,解释会变得非常慢。
【讨论】:
您没有提供足够的信息 - 这取决于您正在创建的对象的具体情况以及您在循环中使用它执行的其他操作。如果对象未创建循环引用,则应在下一次迭代时将其释放。比如代码
for x in range(100000):
obj = " " * 10000000
不会导致内存分配不断增加。
【讨论】:
这是一个旧错误,在 python 2.5 中已针对某些类型进行了更正。发生的事情是 python 不太擅长收集空列表/字典/tupes/floats/ints 之类的东西。在 python 2.5 中,这是固定的……主要是。然而,浮点数和整数是用于比较的单例,因此一旦创建了其中一个,只要解释器还活着,它就会一直存在。在处理大量花车时,我一直被这种最糟糕的情况所困扰,因为它们有一个令人讨厌的独特习惯。这被描述为for python 2.4,并更新了它被折叠成python 2.5
我发现的最好的方法是升级到 python 2.5 或更新版本来处理列表/字典/元组问题。对于数字,唯一的解决方案是不要让大量数字进入 python。我已经用自己的 c++ 对象包装器完成了它,但我的印象是 numpy.array 会给出类似的结果。
作为一个后置脚本,我不知道在 python 3 中发生了什么,但我怀疑数字仍然是单例的一部分。所以内存泄漏其实是语言的一个特性。
【讨论】:
list 会增加 100MB/s 的内存使用量。那是在 2.7 上...所以我猜至少在 2.7 中问题不会退出?我错过了什么吗?
如果您正在创建循环引用,您的对象不会立即被释放,而是必须等待 GC 循环运行。
您可以使用weakref 模块来解决这个问题,或者在使用后显式删除您的对象。
【讨论】:
我发现在我的情况下(使用 Python 2.5.1),循环引用涉及具有 __del__() 方法的类,不仅垃圾收集没有及时发生,我的对象的 __del__() 方法是即使脚本退出,也永远不会被调用。所以我用weakref 打破了循环引用,一切都很好。
感谢 Miles,他在他的 cmets 中提供了所有信息,让我把这些信息放在一起。
【讨论】:
__del__ 方法,则循环不是gc 收集的垃圾。见stackoverflow.com/a/15974956/1959808
您可以在 REPL 执行以下操作来强制取消引用变量:
>>> x = 5
>>> x
5
>>> del x
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
【讨论】:
weakref 可用于循环对象结构化代码,如explained example
【讨论】: