当iterparse
迭代整个文件时,会构建一棵树,并且不会释放任何元素。这样做的好处是元素会记住它们的父元素,并且您可以形成引用祖先元素的 XPath。缺点是会消耗大量内存。
为了在解析时释放一些内存,请使用 Liza Daly 的fast_iter
:
def fast_iter(context, func, *args, **kwargs):
"""
http://lxml.de/parsing.html#modifying-the-tree
Based on Liza Daly's fast_iter
http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
See also http://effbot.org/zone/element-iterparse.htm
"""
for event, elem in context:
func(elem, *args, **kwargs)
# It's safe to call clear() here because no descendants will be
# accessed
elem.clear()
# Also eliminate now-empty references from the root node to elem
for ancestor in elem.xpath('ancestor-or-self::*'):
while ancestor.getprevious() is not None:
del ancestor.getparent()[0]
del context
然后你可以像这样使用它:
def process_element(elem):
print "why does this consume all my memory?"
context = lxml.etree.iterparse('really-big-file.xml', tag='schedule', events=('end',))
fast_iter(context, process_element)
我强烈推荐以上内容所依据的文章fast_iter
;如果您正在处理大型 XML 文件,这对您来说应该特别有趣。
上面介绍的fast_iter
是文章中所示版本的略微修改版本。这个更激进地删除以前的祖先,从而节省更多内存。在这里,您将找到一个演示差异的脚本。