#python #xml #elementtree #iterparse
Вопрос:
Я новичок в xml и python и надеюсь, что правильно сформулировал свою проблему:
У меня есть xml — файлы размером в один гигабайт. Файлы выглядят так:
<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)
Но это печатает только атрибуты первого шага.
Есть ли способ ускорить рабочее решение? Поскольку я довольно новичок в этом деле, я был бы признателен за полный пример или ссылку, в которой я мог бы разобраться сам с помощью примера.
Ответ №1:
Я думаю, что вы на правильном пути iterparse()
.
Возможно, попробуйте указать имя step
элемента в tag
аргументе и обрабатывать только события «пуск»…
from lxml import etree
for event, elem in etree.iterparse("input.xml", tag="step", events=("start",)):
print(elem.attrib)
elem.clear()
РЕДАКТИРОВАТЬ: По какой-то причине я думал, что вы используете lxml, а не ElementTree. Мой ответ потребовал бы, чтобы вы переключились на lxml.
Комментарии:
1. Просто попробовать
lxml
может стоить затраченных усилий… если вы работаете с Python 3.3 или новееlxml
, и стандартныйElementTree
модуль, как правило, имеет схожие характеристики, но в определенных случаях один или другой может быть заметно быстрее; если вы работаете со старыми версиями, тоElementTree
определенно медленнее, хотя вы можете вернутьсяcElementTree
, чтобы получить сопоставимые характеристики2. @Дэниел Хейли, спасибо вам за ваш ответ. Я пытаюсь запустить lxml. ПК компании с ограниченными правами… Я надеюсь, что смогу запустить его на этой неделе.
Ответ №2:
Не зная особенностей вашей настройки, может быть трудно догадаться, что может быть «максимально быстрым» и какая часть задержки вызвана анализом файла. Первое, что я бы сделал, — это, конечно, засек время запуска, чтобы у вас был какой-то начальный ориентир. Затем я бы написал простую программу на python, которая ничего не делает, кроме чтения файла с диска (без анализа XML). Если разница во времени незначительна, то синтаксический анализ XML не является проблемой, и проблема заключается в чтении файла с диска. Конечно, в XML-документе в самом файле нет указания, где заканчивается следующий тег, поэтому пропустить ввод-вывод, связанный с этими частями, невозможно (вам все равно нужно выполнить линейное чтение файла). Кроме потенциального использования другого языка программирования (не интерпретируемого), вы можете сделать не так много вещей.
Если вы действительно получите значительное замедление в результате фактического синтаксического анализа XML, вы можете попытаться предварительно обработать файл в другой. Поскольку формат ваших файлов очень статичен, вы можете прочитать файл и вывести его в другой файл (используя регулярное выражение), пока не получите тег. Затем просто выбросьте данные, пока вы не закроете </step>
тег или </test>
метку. Это приведет к созданию допустимого, но, надеюсь, гораздо меньшего XML-файла. Ключом здесь было бы выполнить «синтаксический анализ» самостоятельно, вместо того, чтобы базовый анализатор пытался понять весь формат документа, что может быть намного быстрее, поскольку ваш формат прост. Затем вы можете запустить свою исходную программу на этом выходе, которая не будет «видеть» никаких посторонних тегов. Конечно, это нарушается, если у вас действительно есть вложенные <step>
теги, но если это так, то вам, вероятно, потребуется проанализировать файл с помощью реального анализатора XML, чтобы понять, где начинается и заканчивается первый уровень.