处理大型 xml 文件。只有根树的子属性是相关的
Processing large xml files. Only root tree children attributes are relevant
我是 xml 和 python 的新手,我希望我的问题表述正确:
我有 xml 个大小为 1 GB 的文件。
文件如下所示:
<test name="LongTestname" result="PASS">
<step ID="0" step="NameOfStep1" result="PASS">
Stuff I dont't care about
</step>
<step ID="1" step="NameOfStep2" result="PASS">
Stuff I dont't care about
</step>
</test>
为了快速分析,我想获取作为根元素子元素的步骤的名称和结果。我不关心的是很多嵌套元素。
我已经尝试过以下操作:
tree = ET.parse(xmlLocation)
root = tree.getroot()
for child in root:
print(child.tag, child.attrib)
这里我遇到了内存错误,因为文件太大了
然后我尝试了:
try:
for event, elem in ET.iterparse(pathToSteps, events=("start","end")):
if elem.tag == "step" and event == "start":
stepAndResult.append([elem.attrib['step'],elem.attrib['result'],"System1"])
elem.clear()
这有效,但速度很慢。我想它会遍历所有元素,这需要很长时间。
然后我找到了一个看起来像这样的解决方案:
try:
tree = ET.iterparse(pathToSteps, events=("start","end"))
_, root = next(tree)
print('ROOT:', root.tag)
except:
print("ERROR: Unable to open and parse file !!!")
for child in root:
print(child.attrib)
但这只打印第一步的属性。
有没有办法加快解决方案的速度?
由于我对这些东西很陌生,我希望能有一个完整的例子或参考,我可以通过一个例子自己弄明白。
在不知道您的设置细节的情况下,可能很难猜测 'fastest possible' 可能是什么以及有多少延迟是由于文件解析造成的。我要做的第一件事当然是给 运行 计时,这样您就有了一些初始基准。然后我会写一个简单的 python 程序,除了从磁盘读取文件(没有 XML 解析)之外什么都不做。如果时间差异不大,那么 XML 解析不是问题,问题是从磁盘读取文件。当然,在 XML 文档中,文件本身没有指示下一个标记结束的位置,因此不可能跳过与这些部分关联的 IO(您仍然需要对文件进行线性读取) .除了可能使用不同的编程语言(非解释型)之外,您可以做的事情可能并不多。
如果在实际的 XML 解析中确实出现明显的速度下降,您可能会尝试将文件预处理为另一个文件。由于文件的文件格式非常静态,您可以读取文件并输出到不同的文件(使用正则表达式),直到获得标签。然后丢弃数据,直到关闭 </step>
标签或 </test>
标签。这将生成一个有效但希望小得多的 XML 文件。这里的关键是自己做 'parsing' 而不是让底层解析器尝试理解所有文档格式,这可能会更快,因为您的格式很简单。然后,您可以 运行 在此输出上的原始程序不会 'see' 任何无关的标签。当然,如果你真的有嵌套的 <step>
标签,这会中断,但如果是这种情况,那么你可能需要用真正的 XML 解析器解析文件以了解第一级开始的位置和停止。
我认为您 iterparse()
的方向是正确的。
也许可以尝试在 tag
参数中指定 step
元素名称并只处理“开始”事件...
from lxml import etree
for event, elem in etree.iterparse("input.xml", tag="step", events=("start",)):
print(elem.attrib)
elem.clear()
编辑: 出于某种原因,我认为您使用的是 lxml 而不是 ElementTree。我的回答会要求您切换到 lxml。
我是 xml 和 python 的新手,我希望我的问题表述正确:
我有 xml 个大小为 1 GB 的文件。 文件如下所示:
<test name="LongTestname" result="PASS">
<step ID="0" step="NameOfStep1" result="PASS">
Stuff I dont't care about
</step>
<step ID="1" step="NameOfStep2" result="PASS">
Stuff I dont't care about
</step>
</test>
为了快速分析,我想获取作为根元素子元素的步骤的名称和结果。我不关心的是很多嵌套元素。
我已经尝试过以下操作:
tree = ET.parse(xmlLocation)
root = tree.getroot()
for child in root:
print(child.tag, child.attrib)
这里我遇到了内存错误,因为文件太大了
然后我尝试了:
try:
for event, elem in ET.iterparse(pathToSteps, events=("start","end")):
if elem.tag == "step" and event == "start":
stepAndResult.append([elem.attrib['step'],elem.attrib['result'],"System1"])
elem.clear()
这有效,但速度很慢。我想它会遍历所有元素,这需要很长时间。
然后我找到了一个看起来像这样的解决方案:
try:
tree = ET.iterparse(pathToSteps, events=("start","end"))
_, root = next(tree)
print('ROOT:', root.tag)
except:
print("ERROR: Unable to open and parse file !!!")
for child in root:
print(child.attrib)
但这只打印第一步的属性。
有没有办法加快解决方案的速度? 由于我对这些东西很陌生,我希望能有一个完整的例子或参考,我可以通过一个例子自己弄明白。
在不知道您的设置细节的情况下,可能很难猜测 'fastest possible' 可能是什么以及有多少延迟是由于文件解析造成的。我要做的第一件事当然是给 运行 计时,这样您就有了一些初始基准。然后我会写一个简单的 python 程序,除了从磁盘读取文件(没有 XML 解析)之外什么都不做。如果时间差异不大,那么 XML 解析不是问题,问题是从磁盘读取文件。当然,在 XML 文档中,文件本身没有指示下一个标记结束的位置,因此不可能跳过与这些部分关联的 IO(您仍然需要对文件进行线性读取) .除了可能使用不同的编程语言(非解释型)之外,您可以做的事情可能并不多。
如果在实际的 XML 解析中确实出现明显的速度下降,您可能会尝试将文件预处理为另一个文件。由于文件的文件格式非常静态,您可以读取文件并输出到不同的文件(使用正则表达式),直到获得标签。然后丢弃数据,直到关闭 </step>
标签或 </test>
标签。这将生成一个有效但希望小得多的 XML 文件。这里的关键是自己做 'parsing' 而不是让底层解析器尝试理解所有文档格式,这可能会更快,因为您的格式很简单。然后,您可以 运行 在此输出上的原始程序不会 'see' 任何无关的标签。当然,如果你真的有嵌套的 <step>
标签,这会中断,但如果是这种情况,那么你可能需要用真正的 XML 解析器解析文件以了解第一级开始的位置和停止。
我认为您 iterparse()
的方向是正确的。
也许可以尝试在 tag
参数中指定 step
元素名称并只处理“开始”事件...
from lxml import etree
for event, elem in etree.iterparse("input.xml", tag="step", events=("start",)):
print(elem.attrib)
elem.clear()
编辑: 出于某种原因,我认为您使用的是 lxml 而不是 ElementTree。我的回答会要求您切换到 lxml。