[英]lxml's iterparse tries to load the whole file into memory
我试图解析一个非常巨大的XML文件,所以我决定为解释使用lxml.iterparse 这里 。
所以我的代码看起来像这样:
import sys
from lxml import etree
def fast_iter(context, func):
for event, elem in context:
func(elem)
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
del context
def launchArticleProcessing(elem):
print elem
context = etree.iterparse(sys.argv[1], events=('end',), tag='text')
fast_iter(context, launchArticleProcessing)
我这样称呼它: python lxmlwtf.py "/path/to/my/file.xml"
内存刚刚填满(直到我杀死进程,因为文件永远不适合它)并且没有任何内容被打印出来。 我在这里错过了什么?
我在这里回答了一个非常相似的问题: lxml和fast_iter占用了所有内存主要原因是因为lxml.etree
仍然在内存中保留了所有未明确lxml.etree
的元素。 因此,您需要手动清除。
我所做的不是过滤您正在寻找的标签的事件:
context = etree.iterparse(open(filename,'r'),events=('end',))
而是手动解析并清除其余部分:
for (event,elem) in progress.bar(context):
if elem.tag == 'text':
# do things here
# every element gets cleared here
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
del context
我的不好,正如我的评论所解释的那样。 lxml将文件加载到内存中,直到找到与给定标记对应的项目。
如果找不到标记(例如因为lxml在其前面添加了命名空间),它只会无限期地将文件加载到内存中,因此问题就出现了。
所以修复是提供正确的标签! 我在我的文件子集上使用常规解析器找到了正确的解析器。
根据我的经验,它可以帮助定期调用垃圾收集器。
像这样的东西可以做到这一点:
import sys
from lxml import etree
def fast_iter(context, func):
for i, (event, elem) in enumerate(context):
# Garbage collect after every 100 elements
if i % 100 == 0:
gc.collect()
func(elem)
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
del context
def launchArticleProcessing(elem):
print elem
context = etree.iterparse(sys.argv[1], events=('end',), tag='text')
fast_iter(context, launchArticleProcessing)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.