我正在尝试解析一个非常庞大的XML文件,因此我决定使用lxml.iterparse,如here所述。
所以我的代码看起来像这样:
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"
内存刚刚填满(直到我杀死进程,因为文件永远不适合它)并且没有任何内容被打印出来。我在这里缺少什么?
答案 0 :(得分:2)
我在这里回答了一个非常类似的问题:lxml and fast_iter eating all the memory主要原因是因为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
答案 1 :(得分:1)
我的不好,正如我的评论中所解释的那样。 lxml将文件加载到内存中,直到找到与给定标记对应的项目。
如果找不到标记(例如因为lxml会将命名空间添加到它中),它只会无限期地将文件加载到内存中,因此会出现问题。
所以修复是提供正确的标签!我在我的文件子集上使用常规解析器找到了正确的解析器。
答案 2 :(得分:0)
根据我的经验,定期调用垃圾收集器可能会有所帮助。
这样的事情可以解决问题:
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)