ファイル全体を反復すると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
上に示したものは、記事に示したもののわずかに変更されたバージョンです。これは、以前の先祖の削除についてより積極的であるため、より多くのメモリを節約できます。ここに、違いを示すスクリプトがあります。