使用iterparse()解析大型XML占用过多内存,有什么替代方案?

3 投票
2 回答
1527 浏览
提问于 2025-04-17 05:27

我正在使用 Python 2.7 和最新的 lxml 库。我在解析一个结构非常统一、包含数百万个元素的大 XML 文件。我原以为 lxml 的 iterparse 方法在解析时不会建立内部树结构,但显然它会,因为内存使用量不断增加,最终导致崩溃(大约在 1GB 左右)。有没有办法用 lxml 解析大 XML 文件而不消耗太多内存呢?

我看到有一个 目标解析器接口 的选项,但我不确定这是否会更有效。

2 个回答

0

我遇到了这个问题,后来在这个网站上得到了一个提示,帮我解决了它:http://effbot.org/zone/element-iterparse.htm#incremental-parsing

elems = ET.Element('MyElements')
for event, elem in ET.iterparse(filename):
    if is_needed(elem): # implement this condition however you like
        elems.append(elem)
    else:
        elem.clear()

这个方法可以让你得到一个只包含所需元素的树结构,而且在解析时不需要占用多余的内存。

2

试试Liza Daly的fast_iter吧:

def fast_iter(context, func, args=[], kwargs={}):
    # http://www.ibm.com/developerworks/xml/library/x-hiperfparse/
    # Author: Liza Daly
    for event, elem in context:
        func(elem, *args, **kwargs)
        elem.clear()
        while elem.getprevious() is not None:
            del elem.getparent()[0]
    del context

fast_iter在解析完元素后,会把它们从树结构中移除,同时也会把一些不再需要的之前的元素(可能是其他标签的)一起移除。

可以这样使用:

import lxml.etree as ET
def process_element(elem):
    ...
context=ET.iterparse(filename, events=('end',), tag=...)        
fast_iter(context, process_element)

撰写回答