强制Python释放对象以释放内存

PyN*_*bie 2 python memory

我正在运行以下代码:

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
Run Code Online (Sandbox Code Playgroud)

如果我从重启开始,python的内存分配/消耗相当小.随着时间的推移,虽然它显着增加,并且最终在大约一天后我的可用内存很少(24GB安装[294 mb free 23960 cached])并且Python在Windows任务管理器列表中声称的内存为3GB.我正在观察在针对文件集合运行代码所需的三天内这种增加.

我的印象是,因为我正在做所有事情

tagged = header.process_tagged('G:')
Run Code Online (Sandbox Code Playgroud)

与每个循环相关联的内存将被释放并进行垃圾回收.

有什么我可以做的来强制释放这个记忆.虽然我还没有运行统计数据但我可以通过观察磁盘上的活动来判断该进程随着时间的推移而减慢(并且内存〜块变大)进展

编辑

我看了下面引用的问题,我不认为这些问题与我在另一个问题中理解的问题相同,即他们抓住对象(三角形列表)并需要整个列表进行计算.在每个循环中,我正在读取文件,执行文件的某些处理,然后将其写回磁盘.然后我正在阅读下一个文件...

关于可能的内存泄漏,我在myObject中使用LXML

注意,自从这个问题的第一次迭代以来,我添加了MyUtilities导入myObject的行.MyUtilities拥有可以完成所有任务的代码

关于发布myUtilities的代码 - 远离基本问题 - 我完成了标题并在标记每次迭代后标记了东西并将结果写入另一个驱动器,事实上是一个新格式化的驱动器.

我研究过使用多处理,但我没有因为一个模糊的想法,因为这是I/O密集型,我将竞争驱动器头 - 也许这是错误的,但因为每次迭代需要我写几百MB文件我认为我会竞争写入甚至读取时间.

更新 - 所以我在myObjectclass中有一个案例,其中打开了一个文件

myString = open(somefile).read()

我改变了

with open(somefile,'r') as fHandle:

`    myString = fHandle.read()`
Run Code Online (Sandbox Code Playgroud)

(抱歉格式化 - 仍然在挣扎)

但是,这没有明显的影响,当我开始一个新的循环时,我有4000 MB的缓存内存,在22分钟后处理27K文件我有大约26000 MB的缓存内存.

我感谢下面的所有答案和评论,并且一直在阅读和测试各种各样的事情.我会更新这个,因为我认为这个任务需要一个星期,现在看起来可能需要一个多月.

我不断收到有关其余代码的问题.然而,它超过800行,对我来说,这有点远离中心问题

因此创建了myObject的实例然后我们将myObject中包含的方法应用于header

这基本上是文件转换.读入文件,并制作文件的部分副本并写入磁盘.

对我来说,核心问题是显然有一些标题标记的持久性.在开始下一个循环之前,如何处理与标题或标记相关的所有内容.

我在过去的14个小时左右一直在运行代码.当它经历第一个周期时,大约需要22分钟来处理27K文件,现在需要一个半小时才能处理大约相同的数字.

只运行gc.collect不起作用.我停止了程序并在解释器中尝试了这一点,我看到内存统计中没有任何动作.

从下面读取memoryallocator描述后编辑我认为缓存中的数量不是问题 - 它是由运行的python进程绑定的数量.所以新的测试是从命令行运行代码.我会继续观看和监控,一旦看到会发生什么,我会发布更多信息.

编辑:仍然苦苦挣扎,但已设置代码从bat文件运行与来自一个循环的数据sgmlFilings(见上文)批处理文件看起来像这样

python batch.py
python batch.py
 .
 .
 .
Run Code Online (Sandbox Code Playgroud)

batch.py​​首先读取一个包含glob目录列表的队列文件,它从列表中取出第一个,更新列表并保存它然后运行headertagged进程.笨拙但由于python.exe在每次迭代后关闭,因此python永远不会累积内存,因此进程以一致的速度运行.

mit*_*ghi 7

原因是CPython的内存管理.Python管理内存的方式使得长时间运行的程序变得困难.当您使用del语句显式释放对象时,CPython必然不会将已分配的内存返回给OS.它保留了记忆,以备将来使用.解决此问题的一种方法是使用多处理模块,并在完成作业并创建另一个作业后终止该过程.这样就可以强制释放内存,操作系统必须释放该子进程使用的内存.我有完全相同的问题.内存使用量随着时间的推移而过度增加,直至系统变得不稳定和无响应.我使用了一种与信号和psutil不同的技术来处理它.例如,当您有一个循环并且需要在堆栈上分配和取消分配数据时,通常会发生此问题.

您可以在此处阅读有关Python内存分配器的更多信息:http://www.evanjones.ca/memoryallocator/

此工具对配置内存使用情况也很有帮助:https://pypi.python.org/pypi/memory_profiler

还有一件事,在myObject中添加插槽,似乎你的对象中有固定的插槽,这也有助于减少ram的使用.没有指定插槽的对象会分配更多ram来处理稍后可能添加到它们的动态属性:http://tech.oyster.com/save-ram-with-python-slots/

  • 只要 Python 重用已释放但未映射的内存,就不会将内存释放给操作系统。特别是,内存使用量应该增长到一定程度,然后稳定下来;它不应该像这里所发生的那样无限地增加。 (2认同)