繁体   English   中英

lxml的iterparse尝试将整个文件加载到内存中

[英]lxml's iterparse tries to load the whole file into memory

我试图解析一个非常巨大的XML文件,所以我决定为解释使用lxml.iterparse 这里

所以我的代码看起来像这样:

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"

内存刚刚填满(直到我杀死进程,因为文件永远不适合它)并且没有任何内容被打印出来。 我在这里错过了什么?

我在这里回答了一个非常相似的问题: lxml和fast_iter占用了所有内存主要原因是因为lxml.etree仍然在内存中保留了所有未明确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

我的不好,正如我的评论所解释的那样。 lxml将文件加载到内存中,直到找到与给定标记对应的项目。

如果找不到标记(例如因为lxml在其前面添加了命名空间),它只会无限期地将文件加载到内存中,因此问题就出现了。

所以修复是提供正确的标签! 我在我的文件子集上使用常规解析器找到了正确的解析器。

根据我的经验,它可以帮助定期调用垃圾收集器。

像这样的东西可以做到这一点:

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM