【发布时间】:2013-07-30 06:25:37
【问题描述】:
我正在尝试将一个大 (5GB) XML 文件(产品目录)解析到一个谷歌数据存储中。我遇到的问题是它占用了大量内存。通过逐行读取并删除元素,我能够从解析部分中获取内存。但是有些东西仍然存在。
我的代码是http://pastebin.com/ESARQikC
我认为问题出在此特定功能中
def process_element(self,item):
if item.tag == "programname":
self.Plist.append(item.text)
elif item.tag == 'name':
self.Plist.append(item.text)
elif item.tag == 'description':
self.Plist.append(item.text)
elif item.tag == 'sku':
self.Plist.append(item.text)
elif item.tag == 'manufacturer':
self.Plist.append(item.text)
elif item.tag == 'price':
self.Plist.append(item.text)
elif item.tag == 'buyurl':
self.Plist.append(item.text)
elif item.tag == 'imageurl':
self.Plist.append(item.text)
elif item.tag == 'advertisercategory':
self.Plist.append(item.text)
elif item.tag=="product":
Product(
programname=("%s" % self.Plist[0]),
name=("%s" % self.Plist[1]),
description=("%s" % self.Plist[2][0:500]),
sku=("%s" % self.Plist[3]),
manufacturer=("%s" % self.Plist[4]),
price=("%s" % self.Plist[5]),
buyurl=("%s" % self.Plist[6]),
imageurl=("%s" % self.getBigImageUrl(self.Plist[7])),
advertisercategory=("%s" % self.Plist[8])).put()
self.count+=1
print self.count
if self.count%15000 == 0:
time.sleep(10000)
for ob in self.Plist:
del ob
del self.Plist
self.Plist=[]
del item
当我注释掉 Product().put() 行并运行它时,它可以通过大量行而不会对内存产生太大影响。我在中间添加睡眠的原因是我在想 GAE 产生的一些子进程正在将数据添加到数据存储中,并且可能需要一些时间来操作。所以我在添加 15000 个项目后等待,看看是否会释放任何 ram(在操作系统端也清除内存),但它没有帮助。这是我的代码中的某些内容,还是与将数据添加到数据存储区相关的某些内容。在玩了几个小时/几天后,我感到困惑和困惑。
【问题讨论】:
-
嗯,我看代码什么都没有。我可能会在本地玩一下,看看我能不能想出点什么。在不使用大量内存的情况下迭代文件方面,您应该使用内置的生成器表达式。
-
在 process_element() 之外调用 gc.collect() 这将强制进行垃圾收集。您的另一种选择是在您的开发盒上运行此过程,通过 remote_api 连接到 prod gae,然后您可以使用尽可能多的内存。不知道为什么你需要睡觉。也无需在循环中执行
del ob。只需将 Plist 分配给新列表即可删除所有引用。再次调用 gc.collect() 将强制进行垃圾收集。请记住 python 使用引用计数,因此如果您在 process_element 之外有任何引用 Plist 中项目的内容,那么 gc 将无济于事。
标签: python google-app-engine memory-management memory-leaks google-cloud-datastore