我正在运行以下代码:
from myUtilities import myObject
for year in range(2006,2015):
front = 'D:\\newFilings\\'
back = '\\*\\dirTYPE\\*.sgml'
path = front + str(year) + back
sgmlFilings = glob.glob(path)
for each in sgmlFilings:
header = myObject(each)
try:
tagged = header.process_tagged('G:')
except Exception as e:
outref = open('D:\\ProblemFiles.txt','a')
outref.write(each '\n')
outref.close()
print each
如果我从重新启动开始,python的内存分配/消耗相当小。随着时间的推移,虽然它显着增加,并且最终在大约一天后我的可用内存很少(24GB安装[294 mb free 23960 cached])并且Python在Windows任务管理器列表中声称的内存为3GB。我正在观察针对文件集运行代码所需的三天内的增长。
我的印象是,因为我正在用
做所有事情tagged = header.process_tagged('G:')
将释放与每个循环相关联的内存并进行垃圾回收。
我能做些什么来强制释放这个记忆。虽然我还没有运行统计数据但我可以通过观察磁盘上的活动来判断该进程随着时间的推移而减慢(并且内存〜块变大)进展
修改
我看了下面引用的问题,我不认为这些问题与我在另一个问题中理解的问题相同,即他们抓住对象(三角形列表)并需要整个列表进行计算。在每个循环中,我正在读取文件,执行文件的某些处理,然后将其写回磁盘。然后我正在阅读下一个文件。 。
关于可能的内存泄漏,我在myObject中使用LXML
注意,自从这个问题的第一次迭代以来,我添加了MyUtilities导入myObject的行。 MyUtilities拥有执行所有操作的代码
关于发布myUtilities的代码 - 远离基本问题 - 我完成了标题并在每次迭代标记后标记了东西并将结果写入另一个驱动器,实际上是一个新格式化的驱动器。
我研究过使用多处理,但我没有因为一个模糊的想法,因为这是I / O密集型,我将竞争驱动器头 - 也许这是错误的,但因为每次迭代都需要我写几百MB的文件,我想我会竞争写作甚至是读时间。
UPDATE - 所以我在myObjectclass中有一个用
打开文件的案例 myString = open(somefile).read()
我把它改为
with open(somefile,'r') as fHandle:
` myString = fHandle.read()`
(抱歉格式化 - 仍然在苦苦挣扎)
然而,这没有明显的影响,当我开始一个新的循环时,我有4000 MB的缓存内存,在22分钟后处理27K文件我有大约26000 MB的缓存内存。
我感谢下面的所有答案和评论,并且一直在阅读和测试各种各样的事情。我会更新这个,因为我认为这个任务需要一个星期,现在看起来可能需要一个多月。
我不断收到有关其余代码的问题。然而,它超过800行,对我而言,远离中心问题
因此创建了myObject的实例 然后我们将myObject中包含的方法应用于标题
这基本上是文件转换。读入文件,并制作文件的部分副本并将其写入磁盘。
对我来说,核心问题是显然存在一些标题或标记的持久性。在开始下一个循环之前,如何处理与标题或标记相关的所有内容。
我过去14个小时左右一直在运行代码。当它经历了第一个周期时,大约需要22分钟来处理27K文件,现在需要一个半小时才能处理大约相同的数字。
只是运行gc.collect不起作用。我停止了程序并在解释器中尝试了这一点,我看到内存统计中没有任何动作。
从下面读取memoryallocator描述后编辑我认为缓存中的数量不是问题 - 它是由正在运行的python进程绑定的数量。所以新的测试是从命令行运行代码。我会继续观看和监控,一旦看到会发生什么就会发布更多信息。
编辑:仍然在苦苦挣扎,但已设置代码从bat文件运行,其中包含来自sgmlFilings
的一个循环的数据(见上文),批处理文件看起来像这样
python batch.py
python batch.py
.
.
.
batch.py首先读取一个包含glob目录列表的队列文件,它从列表中取出第一个,更新列表并保存,然后运行header
和{{ 1}}进程。笨拙但由于python.exe在每次迭代后关闭,因此python永远不会累积内存,因此进程以一致的速度运行。
答案 0 :(得分:6)
原因是CPython的内存管理。 Python管理内存的方式使得长时间运行的程序变得困难。当您使用del语句显式释放对象时,CPython必然不会将已分配的内存返回给OS。它保留了记忆,以备将来使用。解决此问题的一种方法是使用多处理模块,并在完成作业并创建另一个作业后终止该过程。这样就可以强制释放内存,操作系统必须释放该子进程使用的内存。 我有完全相同的问题。内存使用量随着时间的推移而过度增加,直至系统变得不稳定和无响应。我使用了一种与信号和psutil不同的技术来处理它。例如,当您有一个循环并且需要在堆栈上分配和释放数据时,通常会发生此问题。
您可以在此处阅读有关Python内存分配器的更多信息:MouseButtons
此工具对配置内存使用情况也很有帮助:http://www.evanjones.ca/memoryallocator/
还有一件事,将插槽添加到myObject,似乎你的对象中有固定的插槽,这也有助于减少ram的使用。未指定广告位的对象会分配更多ram来处理您稍后可能添加的动态属性:https://pypi.python.org/pypi/memory_profiler
答案 1 :(得分:2)
您可以使用gc
模块强制进行垃圾回收。特别是gc.collect()
函数。
然而,这可能无法解决您的问题,因为gc 可能正在运行,但您要么使用包含内存泄漏的库/代码,要么库/代码在某处保留了一些引用。在任何情况下,我怀疑gc是这里的问题。
有时候你可能会有一些代码可以保存对你想要的对象的引用。在这种情况下,您可以在不再需要时明确考虑del
,但事实并非如此。
还要记住,python进程的内存使用量实际上可能比操作系统报告的要小得多。特别是对free()
的调用不需要将内存返回给操作系统(通常这在执行小分配时不会发生)所以你看到的可能是内存使用率达到最高点,而不是目前的用法。除此之外,Python在C&#39之上使用了另一层内存分配,这使得分析内存使用非常困难。
然而,内存不断上升,这可能并非如此。
您应该使用类似Guppy
的内容来分析内存使用情况。
答案 2 :(得分:1)
答案 3 :(得分:1)
在诉诸强制垃圾收集之前(绝不是个好主意);尝试一些基本的东西:
使用glob.iglob
,(生成器)而不是一次获取所有文件的列表。
在myObject(each)
方法中,确保您关闭文件或使用with statement
,以便自动关闭;否则它会留在记忆中占用空间。
不要打开和关闭文件;只需打开文件一次,即可在异常处理程序中写入。
由于您尚未发布正在进行处理的实际代码(因此,可能是造成内存困难的原因),因此很难推荐具体内容。