【问题标题】:Memory error when repairing malformed xml修复格式错误的 xml 时出现内存错误
【发布时间】:2020-02-19 17:57:57
【问题描述】:

我有一些非常大的格式错误的 XML - 它缺少顶级标记并且有重复的属性。为了解决这个问题,我在我的格式错误的 XML 的一个子集上测试了以下解决方案,它可以完美地添加标签并使用 BeautifulSoup 自动删除重复的属性。

import sys
from bs4 import BeautifulSoup
import xml.etree.ElementTree as ET

flow_file = sys.stdin.read()

try:
    tree = ET.fromstring(flow_file)
    sys.stdout.write(flow_file)
except:
    flow_file = f"<dispatch>{flow_file}</dispatch>"
    soup = BeautifulSoup(flow_file, 'xml')
    sys.stdout.write(soup)

但是,由于我的真实文件太大,它会引发内存错误。由于我需要(AFAICT)完整的 XML 来添加顶级标签并删除重复项,因此我不太确定如何修改我的代码来处理如此大的 XML。我看到了一些关于使用lxml 和迭代的建议,但我不清楚它如何适合我的需求/流程。

ETA:不确定是否有帮助,但重点是清理文件,以便它可以通过 NiFi 的 SplitXML 处理器运行。

【问题讨论】:

  • 如果它是一个文件,你是否可以尝试不一次读取它,而是使用 ElementTree 的 iterparse 代替?我曾经用这种方法解析了几个 GB 的文件。 for event, elem in etree.iterparse("big.xml", events=('start', 'end')): 然后处理内容,最后if event == "end": root.clear() 清除内存。如果这是您正在寻找的,我将发布更详细的答案。
  • @n00by0815 这看起来完全符合我的需要,但我能否按照我的需要使用 BeautifulSoup? (删除重复的属性)
  • 我并没有在你的帖子中看到你对数据做了什么。我所做的是找到一个元素的打开标记,占用该元素中的所有内容,根据需要处理它(在你的情况下,可能写入输出 xml)并清除根,所以我的 ram没有跑满。我将发布一些代码作为答案,您可以自己查看是否可用。

标签: python beautifulsoup lxml elementtree large-files


【解决方案1】:

由于我真的不知道你如何处理数据,这里是我对几个 GB 大 xml 文件采取的方法:

import xml.etree.ElementTree as etree

root = False
#iterparse file, get event tags start and end
for event, elem in etree.iterparse("my_big.xml", events=('start', 'end')):
#set first element as rootelement, so we can clear it later
    if event == "start" and root == "False":
        root = elem
#Here we look for a certain end tag
    if event == "end" and elem.tag == "TAGOFINTEREST":
#set found False, so we can break, as soon, as we found our DataOfInterest
        found = False
#iterate through children and iterate over child nodes
#HERE I guess you would work with pandas
        for stuff in elem.getchildren():
#if found == True stop iterating or whatever condition you have
            if found:
                break
             #look for what you need, set found to True and break the 
             found = True
#clear elem, in order to save RAM
        elem.clear()

#Might require revision clears RAM after every "end" event
    if event == "end":
        root.clear()

我希望这会有所帮助。

【讨论】:

  • 这看起来不错,但是它失败了,因为 XML 格式错误——这就是为什么我尝试使用 BeautifulSoup 进行解析。
  • try: do_something() except: do_something_else() 捕获异常也不起作用?如果它因某个错误消息而失败,请同时更新您的帖子,因为这样可以更轻松地进行故障排除。或者发布一些示例 xml。
猜你喜欢
  • 2011-08-09
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 2015-06-19
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多