Ответ 1
Поскольку iterparse
выполняет итерацию по всему файлу, дерево строится и никакие элементы не освобождаются. Преимущество этого заключается в том, что элементы помнят, кто их родитель, и вы можете сформировать XPaths, которые относятся к элементам предка. Недостатком является то, что он может потреблять много памяти.
Чтобы освободить некоторую память при анализе, используйте Liza Daly fast_iter
:
def fast_iter(context, func, *args, **kwargs):
"""
http://lxml.de/parsing.html#modifying-the-tree
Based on Liza Daly 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 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
представляет собой слегка измененную версию показанного
в статье. Это более агрессивно относится к удалению предыдущих предков,
таким образом экономит больше памяти. Здесь вы найдете script, который демонстрирует
разница.