【问题标题】:Large XML File Parsing in PythonPython 中的大型 XML 文件解析
【发布时间】:2020-10-16 02:33:50
【问题描述】:

我有一个大小为 4 GB 的 XML 文件。我想解析它并将其转换为数据框来处理它。但由于文件太大,以下代码无法将文件转换为 Pandas 数据框。代码只是不断加载,不提供任何输出。但是当我将它用于较小尺寸的类似文件时,我得到了正确的输出。

任何人都可以提出任何解决方案。也许是一个代码可以加快从 XML 到 Data Frame 的转换过程或将 XML 文件拆分为更小的子集。

我是否应该在我的个人系统(2 GB RAM)上处理如此大的 XML 文件或者我应该使用 Google Colab 的任何建议。如果是 Google Colab,那么有什么方法可以更快地将如此大的文件上传到驱动器,从而更快地上传到 Colab?

以下是我使用的代码:

import xml.etree.ElementTree as ET
tree = ET.parse("Badges.xml")
root = tree.getroot()

#Column names for DataFrame
columns = ['row Id',"UserId",'Name','Date','Class','TagBased']

#Creating DataFrame
df = pd.DataFrame(columns = columns)

#Converting XML Tree to a Pandas DataFrame

for node in root: 
    
    row_Id = node.attrib.get("Id")
    UserId = node.attrib.get("UserId")
    Name = node.attrib.get("Name")
    Date = node.attrib.get("Date")
    Class = node.attrib.get("Class")
    TagBased = node.attrib.get("TagBased")
    
    df = df.append(pd.Series([row_Id,UserId,Name,Date,Class,TagBased], index = columns), ignore_index = True)

以下是我的 XML 文件:

<badges>
  <row Id="82946" UserId="3718" Name="Teacher" Date="2008-09-15T08:55:03.923" Class="3" TagBased="False" />
  <row Id="82947" UserId="994" Name="Teacher" Date="2008-09-15T08:55:03.957" Class="3" TagBased="False" />
  <row Id="82949" UserId="3893" Name="Teacher" Date="2008-09-15T08:55:03.957" Class="3" TagBased="False" />
  <row Id="82950" UserId="4591" Name="Teacher" Date="2008-09-15T08:55:03.957" Class="3" TagBased="False" />
  <row Id="82951" UserId="5196" Name="Teacher" Date="2008-09-15T08:55:03.957" Class="3" TagBased="False" />
  <row Id="82952" UserId="2635" Name="Teacher" Date="2008-09-15T08:55:03.957" Class="3" TagBased="False" />
  <row Id="82953" UserId="1113" Name="Teacher" Date="2008-09-15T08:55:03.957" Class="3" TagBased="False" />

【问题讨论】:

  • 另一种方法不是解析整个 XML,而是首先创建 250MB 大的块,然后并行解析它们。或者,当然,这仅在 XML 是一个类似长列表的结构时才有效,比如您知道会发生什么的事务、人员或项目。您可以有一个阅读器并跳转到文件中的 250MB 左右并找到正确的切割点,然后再次重新跳转等...
  • @user3184950 你能写出将XML文件转换成小块的代码吗?我试过了,但我遇到了问题。
  • @Parfait 您能否建议您提到的替代代码。
  • 拆分大文件很大程度上取决于 XML 的结构。一个非常可搜索的主题并在上面找到示例代码,就像这里在堆栈中一样

标签: python-3.x xml pandas dataframe xml-parsing


【解决方案1】:

考虑使用cElementTree 而不是ElementTree

https://effbot.org/zone/celementtree.htm

cElementTree 模块是 ElementTree API 的 C 实现,针对快速解析和低内存使用进行了优化。在典型文档上,cElementTree 比 Python 版本的 ElementTree 快 15-20 倍,并且使用的内存少 2-5 倍。

cElementTree 模块旨在替换标准 elementtree 包中的 ElementTree 模块。理论上,你应该可以简单地改变:

from elementtree import ElementTree

import cElementTree as ElementTree

【讨论】:

  • 我尝试使用 cElementTree,但我遇到了同样的问题。代码卡住了,没有产生输出。它只是继续加载。您能否建议一些其他版本的代码或将我的 xml 文件转换为较小文件的代码?
【解决方案2】:

考虑使用iterparse 进行快速流处理,以增量方式构建树。在每次迭代中构建一个字典列表,然后您可以将其传递到 pandas.DataFrame 构造函数 once 外部循环。下面调整根子节点的重复节点名称:

from xml.etree.ElementTree import iterparse
#from cElementTree import iterparse
import pandas as pd

file_path = r"/path/to/Input.xml"
dict_list = []

for _, elem in iterparse(file_path, events=("end",)):
    if elem.tag == "row":
        dict_list.append({'rowId': elem.attrib['Id'],
                          'UserId': elem.attrib['UserId'],
                          'Name': elem.attrib['Name'],
                          'Date': elem.attrib['Date'],
                          'Class': elem.attrib['Class'],
                          'TagBased': elem.attrib['TagBased']})

        # dict_list.append(elem.attrib)      # ALTERNATIVELY, PARSE ALL ATTRIBUTES

        elem.clear()

df = pd.DataFrame(dict_list)

【讨论】:

  • 我使用了你提供的代码,加载需要 40 分钟,但我遇到了很多错误,如下所述。
  • 我已经添加了XML文件,请看一下。
  • 我写的代码没有输出,因为每次在 DataFrame 中追加都需要很长时间,使用您的方法追加到字典中不仅给了我一个输出,而且花费了相当长的时间更少的时间。
  • 我对几乎相同的 XML 文件使用了相同的代码,但遇到了一个不应该发生的关键错误。如果可能的话,请看看这个问题。链接:stackoverflow.com/questions/62660270/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-23
  • 2011-05-09
  • 2015-09-15
  • 1970-01-01
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
相关资源
最近更新 更多