【发布时间】:2014-12-01 20:45:11
【问题描述】:
我有一个 python 脚本,它正在处理来自压缩 ASCII 的大量数据。一段时间后,它会耗尽内存。我不是在构建大型列表或字典。下面的代码说明了这个问题:
import struct
import zlib
import binascii
import numpy as np
import psutil
import os
import gc
process = psutil.Process(os.getpid())
n = 1000000
compressed_data = binascii.b2a_base64(bytearray(zlib.compress(struct.pack('%dB' % n, *np.random.random(n))))).rstrip()
print 'Memory before entering the loop is %d MB' % (process.get_memory_info()[0] / float(2 ** 20))
for i in xrange(2):
print 'Memory before iteration %d is %d MB' % (i, process.get_memory_info()[0] / float(2 ** 20))
byte_array = zlib.decompress(binascii.a2b_base64(compressed_data))
a = np.array(struct.unpack('%dB' % (len(byte_array)), byte_array))
gc.collect()
gc.collect()
print 'Memory after last iteration is %d MB' % (process.get_memory_info()[0] / float(2 ** 20))
打印出来:
Memory before entering the loop is 45 MB
Memory before iteration 0 is 45 MB
Memory before iteration 1 is 51 MB
Memory after last iteration is 51 MB
在第一次和第二次迭代之间,创建了 6 MB 的内存。如果我运行循环两次以上,内存使用量将保持在 51 MB。如果我把解压的代码放到它自己的函数中,并把实际的压缩数据提供给它,那么内存使用量将继续增长。我正在使用 Python 2.7。为什么内存在增加,如何纠正?谢谢。
【问题讨论】:
-
我不会说,那是内存泄漏,这是正常的内存消耗。
-
除了看起来很正常,正如@Daniel 所说,
byte_array和a = np.array怎么样?您的第一次迭代在实例化它们之前输出内存使用情况。这听起来像是很多数据,很可能不会被垃圾收集器销毁,因为您在for循环范围内调用它。取消缩进(向左移动)gc.collect(),使其在for循环之外运行,看看会发生什么。 -
@BorrajaX 在最后一次打印之前和循环退出之后添加了另一个 gc.collect,没有变化。对于所有打印语句,byte_array 和“a”变量不应该存在于内存中
-
对不起,对不起......即使在
for循环之后,byte_array和a也在你的范围内(我的错,它们不会被破坏)。在循环结束后(以及在您刚刚添加的第二个gc.collect()之前)执行byte_array = Nonea=None... 现在我自己很好奇 :-) -
@BorrajaX 在那些设置为 None 的语句中添加了它,它清除了内存,解决了我的担忧。我误解了 Python 范围,我更习惯于 Java。无论如何,我的代码中仍然存在问题,但上面的示例没有正确显示它。谢谢
标签: python memory-leaks