Если отдельные элементы* Разве не оптимальные Размер чанка для использования итеративными анализаторами, тогда какой размер оптимального чанка? В частности, где выбранные размеры чанков документированы для популярных библиотек LXML и встроенного Python xml.etree.elementtree ?
У меня, кажется, есть Обходной путь для изменения размера чанка по умолчанию (например, на отдельные линии в качестве доказательства концепции), в то же время используя одни и те же итеративные анализаторы и не разрабатывая новый, но я хочу знать, есть ли Лучшее, широко известное решение, чем мой несколько взломанного обходного пути.
* Примечание: в высоко структурированном примере XML документы, оптимизированные для чтения человека, обычно каждая строка соответствует Единственный открытие или закрывающая метка одного элемента, поэтому возможно, что некоторые размеры кусок могут быть измерены с точки зрения количества строк. Диаграммы, измеряющие размеры кусок в количестве символов, могут быть более правдоподобными.
Что я пробовал: я бы предпочел не использовать саксофон, потому что это требует много смущающе структурированных Код паболка. xml.etree.elementtree ) обсуждается, часто звучит так, как будто он анализирует файлы XML «итеративно», как в элементе за элементом/тегом (см. Примечание выше). < Br /> Но кажется, что на практике, учитывая файловый объект в качестве ввода, оба анализатора ищут и анализируют вывод метода .Read < /code> этого файлоподобного объекта. (В отличие от вывода .Readline , как я ожидал.) Если этот файл-подобный объект является файловым указателем для файла 8 ГБ, и он работает на узле кластера с памятью 2 ГБ, это, конечно вызвать ошибку OOM. < /p>
Код: Выделить всё
.read
Код: Выделить всё
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")
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 ... rs-in-pyth