如果使用ElementTree.iterparse()时明确()ING树木当内存使用的增加?(Sho

2019-09-16 10:49发布

import os
import xml.etree.ElementTree as et

for ev, el in et.iterparse(os.sys.stdin):
    el.clear()

运行在ODP结构上面的RDF转储结果总是增加内存。 这是为什么? 我明白了ElementTree的还是建立一个解析树,尽管子节点clear()版。 如果是这样的内存使用模式的原因,是有办法解决它?

Answer 1:

你是clear荷兰国际集团每一个元素,但对它们的引用留根文件内。 所以各个元素仍然不能被垃圾收集。 见这个讨论了ElementTree文档。

解决的办法是明确提到根,就像这样:

# get an iterable
context = iterparse(source, events=("start", "end"))

# turn it into an iterator
context = iter(context)

# get the root element
event, root = context.next()

for event, elem in context:
    if event == "end" and elem.tag == "record":
        ... process record elements ...
        root.clear()

要记住的内存使用,这可能不是会影响您的情况的另一件事是,一旦虚拟机分配从系统堆存储器,一般从不给内存回来。 大多数Java虚拟机的工作也是这样的。 所以,你不应该指望在解释的大小topps永远降低,即使堆内存的使用。



Answer 2:

正如凯文·格拉在答复中提到,在“root.clear()”战略的ElementTree文档中能消除完全解析根的孩子。 如果这些孩子锚固巨大分支,它不是非常有帮助。

他谈到了理想的解决方案,但并没有发布任何代码,所以这里是一个例子:

element_stack = []
context = ET.iterparse(stream, events=('start', 'end'))
for event, elem in context:
    if event == 'start':
        element_stack.append(elem)
    elif event == 'end':
        element_stack.pop()
        # see if elem is one of interest and do something with it here
        if element_stack:
            element_stack[-1].remove(elem)
del context

利益不会有子元素的元素; 他们会一直在尽快结束其标签被视为删除。 如果你需要的是元素的文字或属性,这可能是确定。

如果您想查询到该元素的后代,你需要让一个完整的分支来为它建造。 为此,保持一个标志,因为这些元素的深度计数器来实现。 只有调用一个.remove()时,深度为零:

element_stack = []
interesting_element_depth = 0
context = ET.iterparse(stream, events=('start', 'end'))
for event, elem in context:
    if event == 'start':
        element_stack.append(elem)
        if elem.tag == 'foo':
            interesting_element_depth += 1
    elif event == 'end':
        element_stack.pop()
        if elem.tag == 'foo':
            interesting_element_depth -= 1
            # do something with elem and its descendants here
        if element_stack and not interesting_element_depth:
            element_stack[-1].remove(elem)
del context


Answer 3:

我遇到了同样的问题。 文档没有使事情很清楚。 在我的情况的问题是:

1)调用清晰并释放内存的子节点。 文件说,它释放所有内存。 清除不释放那些明确被称为内存,因为该内存属于哪个分配它的母公司。 2)调用root.clear(),那要看是什么样的根。 如果根是父,然后它会工作。 否则,将不会释放内存。

此修复程序是保留对父的引用,当我们不再需要的节点,我们称之为parent.remove(child_node)。 这个工作,它保留了存储配置文件在几KB。



文章来源: Should memory usage increase when using ElementTree.iterparse() when clear()ing trees?