【问题标题】:python xml iterating over elements takes a lot of memorypython xml迭代元素需要大量内存
【发布时间】:2018-06-06 09:08:36
【问题描述】:

我有一些非常大的 XML 文件(每个大约 100-150 MB)。

我的 XML 中的一个元素是 M(对于成员),它是 HH(家庭)的子元素 -

即- 每个家庭都有一个或多个成员。

我需要做的是获取满足某些条件的所有成员(条件可以改变,并且可以在家庭和成员上 - 例如 - 只是来自高收入家庭的成员(对家庭的限制) ),谁的年龄在 18-49 岁之间(对成员的限制)) - 并在一个相当复杂的函数中进一步处理它们。

这就是我正在做的:

import lxml.etree as ET
all_members=[]
tree=ET.parse(whole_path)
root=tree.getroot()
HH_str='//H' #get all the households
HH=tree.xpath(HH_str)
for H in HH:
'''check if the hh satisfies the condition'''
    if(is_valid_hh(H)):
        M_str='.//M'
        M=H.xpath(M_str)
        for m in M:
            if(is_valid_member(m)):
                all_members.append(m)

for member in all_members:
'''do something complicated'''

问题在于它占用了我所有的内存(我有 32 GB)! 如何更有效地迭代 xml 元素?

任何帮助将不胜感激...

【问题讨论】:

  • @Tai - 我尝试使用iterparse(),但不知道如何使用。你能帮我吗?
  • 我可以提供您的数据样本吗?
  • 很遗憾,它是保密的。但我以一种相当笼统的形式写了这个问题......
  • @BinyaminEven 匿名化你的数据块,或者用你自己的数据组成一些具有相同结构的类似数据并在这里分享。这样人们就可以迅速解决您的问题。

标签: python xml list xpath generator


【解决方案1】:

etree 会消耗大量内存(是的,即使使用iterparse()),而sax 真的很笨重。但是,pulldom 来救援!

from xml.dom import pulldom
doc = pulldom.parse('large.xml')
for event, node in doc:
    if event == pulldom.START_ELEMENT and node.tagName == 'special': 
        # Node is 'empty' here       
        doc.expandNode(node)
        # Now we got it all
        if is_valid_hh(node):
            ...do things...

它是那些不需要使用它的人似乎都不知道的库之一。文档在例如https://docs.python.org/3.7/library/xml.dom.pulldom.html

【讨论】:

  • iterparse() 对于 OP 的情况应该没问题。 OP的文件是不是太大了?但很高兴知道另一个图书馆。
  • 快速测试(在 Windows 上)显示即使是 300MB 的文件也可能需要超过 2GB 的空间来使用 iterparse 进行解析 - 可能取决于内容?无论哪种方式,如果在除开发站之外的任何设备上运行,都会有大量的意外内存使用。
  • 不确定。我之前在我的 3GB 内存笔记本电脑上解析了一个 1GB 的文件,这很好。您是否在不需要时清理了根目录?
猜你喜欢
  • 1970-01-01
  • 2021-12-19
  • 2021-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
相关资源
最近更新 更多