Как лучше всего разобрать линию файла XML в Python, без использования SAX? (`iterParse` ведет себя неожиданно) [Закрыто]Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как лучше всего разобрать линию файла XML в Python, без использования SAX? (`iterParse` ведет себя неожиданно) [Закрыто]

Сообщение Anonymous »

Вопрос: Как лучше всего разобрать файл XML в линии Python? Для использования итеративными анализаторами, тогда какой размер оптимального чанка? В частности, где выбранные размеры чанков документированы для популярных библиотек LXML и встроенного Python xml.etree.elementtree ?
У меня, кажется, есть Обходной путь для изменения размера чанка по умолчанию (например, на отдельные линии в качестве доказательства концепции), в то же время используя одни и те же итеративные анализаторы и не разрабатывая новый, но я хочу знать, есть ли Лучшее, широко известное решение, чем мой несколько взломанного обходного пути. Код с паттерной пластинкой.
Как iterparse (оба из lxml.etree и xml.etree.elementtre ) Обсуждается, это часто звучит так, как будто он анализирует XML-файлы «итеративно», как в строке по строке. , оба анализатора ищут и анализируют вывод метода .Read этого файлового объекта. (В отличие от вывода .Readline , как я ожидал.) Если этот файл-подобный объект является файловым указателем для файла 8 ГБ, и он работает на узле кластера с памятью 2 ГБ, это, конечно вызвать ошибку OOM. < /p>
Этот вывод основан на этом ответе на связанный вопрос, а также на мое собственное тестирование. Вот MWE: < /p>

Код: Выделить всё

import io
from lxml import etree
import xml.etree.ElementTree as etree2

xml_string = """







Manager

Star Team Member




"""

#### lxml output

for event, element in etree.iterparse(io.BytesIO(xml_string.encode("UTF-8")), recover=True, remove_blank_text=True,
events=("start", "end",)):
print(str((event, element, element.tag,
element.text.strip() if element.text is not None else element.text,
element.tail.strip() if element.tail is not None else element.tail)) + "\n")
print(f"{etree.tostring(element)}\n")

### xml.etree.ElementTree output is the same

for event, element in etree2.iterparse(io.BytesIO(xml_string.encode("UTF-8")),
events=("start", "end",)):
print(str((event, element, element.tag,
element.text.strip() if element.text is not None else element.text,
element.tail.strip() if element.tail is not None else element.tail)) + "\n")
print(f"{etree2.tostring(element)}\n")

Уже на самой первой итерации, строковое представление корневого тега представляет весь документ XML, что предполагает, что весь вывод .Read уже был проанализирован, скорее чем просто первая строка (что я изначально думал, что первая итерация должна была соответствовать на основе обсуждения других итерпара вверх со следующим Обходной путь, который отображает ожидаемое поведение в линии. Тем не менее, мне интересно, есть ли лучшие решения. Например, приведут ли миллионы вызовов в чтении < /code>, которые должны быть сделаны для ~ 8 ГБ файла. ">### for the MWE

class StreamString(object):

def __init__(self, string):
self._io = io.StringIO(string)

def read(self, len=None):
return self._io.readline().encode("UTF-8")

def close(self):
self._io.close()

### closer to what would be used in practice

class StreamFile(object):

def __init__(self, path):
self._file = open(path, "r")

def read(self, len=None):
return self._file.readline().encode("UTF-8")

def close(self):
self._file.close()

### demonstrating the expected line-by-line parsing behavior

iterator = etree.iterparse(StreamString(xml_string), recover=True, remove_blank_text=True,
events=("start", "end",))
event, root = next(iterator)
print(str((event, root, root.tag,
root.text.strip() if root.text is not None else root.text,
root.tail.strip() if root.tail is not None else root.tail)) + "\n")
print(f"{etree.tostring(root)}\n")

for event, element in iterator:
print(str((event, element, element.tag,
element.text.strip() if element.text is not None else element.text,
element.tail.strip() if element.tail is not None else element.tail)) + "\n")
print(f"{etree.tostring(root)}\n")

< /code>
Это демонстрирует ожидаемое поведение, где проанализированное дерево, соответствующее корневому элементу, последовательно растет с каждой итерацией, когда добавляются новые линии. Такое поведение также легче понять и объединять с многочисленными предложениями на этом сайте о том, как очистить следы памяти, соответствующие узлам и их предкам (и все их «старшие» в глубине первого поиска братьев и сестер) после их разбора. Мне неясно, почему это не поведение по умолчанию. Для XML-файлов, которые потенциально являются гигабайтами по размеру на узлах кластера с 1-2 ГБ памяти. (У меня нет контроля над средой Compute, да, я согласен, было бы больше смысла просто масштабироваться вертикально к одному узлу с ~ 64 ГБ памяти.)


Подробнее здесь: https://stackoverflow.com/questions/793 ... hout-using
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»