Python sax для lxml для 80 + GB XML

Как бы вы прочитали XML-файл с использованием sax и преобразовали его в элемент lxml etree.iterparse?

Чтобы предоставить обзор проблемы, я создал инструмент для анализа XML с использованием lxml для XML-фида, который будет варьироваться в размере 25-500 МБ, который требует приема внутрь на двухдневной основе, но ему необходимо выполнить однократное проглатывание файл размером 60 – 100 ГБ.

Я решил использовать lxml на основе спецификаций, которые детализировали узел, не превышал бы размер 4-8 ГБ, который, как я думал, позволит считывать информацию в памяти и очищаться по завершении.

Обзор, если код ниже

elements = etree.iterparse( self._source, events = ('end',) ) for event, element in elements: finished = True if element.tag == 'Artist-Types': self.artist_types(element) def artist_types(self, element): """ Imports artist types :param list element: etree.Element :returns boolean: """ self._log.info("Importing Artist types") count = 0 for child in element: failed = False fields = self._getElementFields(child, ( ('id', 'Id'), ('type_code', 'Type-Code'), ('created_date', 'Created-Date') )) if self._type is IMPORT_INC and has_artist_type(fields['id']): if update_artist_type(fields['id'], fields['type_code']): count = count + 1 else: failed = True else: if create_artist_type(fields['type_code'], fields['created_date'], fields['id']): count = count + 1 else: failed = True if failed: self._log.error("Failed to import artist type %s %s" % (fields['id'], fields['type_code']) ) self._log.info("Imported %d Artist Types Records" % count) self._artist_type_count = count self._cleanup(element) del element 

Дайте мне знать, могу ли я добавить какие-либо разъяснения.

2 Solutions collect form web for “Python sax для lxml для 80 + GB XML”

iterparse – итеративный синтаксический анализатор. Он будет испускать объекты и события Element и постепенно наращивать все дерево Element при его анализе, поэтому в итоге он будет иметь все дерево в памяти.

Тем не менее, легко иметь ограниченное поведение в памяти: удалите ненужные элементы, когда вы их разбираете.

Типичная рабочая нагрузка «гигантский xml» – это один корневой элемент с большим количеством дочерних элементов, которые представляют записи. Я предполагаю, что это такая структура XML, с которой вы работаете?

Обычно достаточно использовать clear() для удаления элемента, который вы обрабатываете. Использование вашей памяти будет немного расти, но это не очень. Если у вас действительно огромный файл, то даже пустые объекты Element будут потреблять слишком много, и в этом случае вы также должны удалить ранее просматриваемые объекты Element . Обратите внимание, что вы не можете безопасно удалить текущий элемент. Документация lxml.etree.iterparse описывает этот метод .

В этом случае вы будете обрабатывать запись каждый раз, когда будет найдена </record> , тогда вы удалите все предыдущие элементы записи.

Ниже приведен пример использования бесконечно длинного XML-документа. Он будет печатать использование памяти процесса, когда он анализирует. Обратите внимание, что использование памяти стабильно и не продолжает расти.

 from lxml import etree import resource class InfiniteXML (object): def __init__(self): self._root = True def read(self, len=None): if self._root: self._root=False return "<?xml version='1.0' encoding='US-ASCII'?><records>\n" else: return """<record>\n\t<ancestor attribute="value">text value</ancestor>\n</record>\n""" def parse(fp): context = etree.iterparse(fp, events=('end',)) for action, elem in context: if elem.tag=='record': # processing goes here pass #memory usage print resource.getrusage(resource.RUSAGE_SELF).ru_maxrss # cleanup # first empty children from current element # This is not absolutely necessary if you are also deleting siblings, # but it will allow you to free memory earlier. elem.clear() # second, delete previous siblings (records) while elem.getprevious() is not None: del elem.getparent()[0] # make sure you have no references to Element objects outside the loop parse(InfiniteXML()) 

Я нашел этот полезный пример на http://effbot.org/zone/element-iterparse.htm . Смелый акцент – мой.

Инкрементальный анализ #

Обратите внимание, что iterparse все еще строит дерево, как и синтаксический анализ, но вы можете безопасно изменить или удалить части дерева при разборе. Например, чтобы анализировать большие файлы, вы можете избавиться от элементов, как только вы их обработали:

 for event, elem in iterparse(source): if elem.tag == "record": ... process record elements ... elem.clear() 

Вышеупомянутый шаблон имеет один недостаток; он не очищает корневой элемент, поэтому вы получите один элемент с множеством пустых дочерних элементов. Если ваши файлы огромны, а не просто большие, это может быть проблемой. Чтобы обойти это, вам нужно взять верх над корневым элементом. Самый простой способ сделать это – включить начальные события и сохранить ссылку на первый элемент переменной:

 # get an iterable context = iterparse(source, events=("start", "end")) # turn it into an iterator context = iter(context) # get the root element event, root = context.next() for event, elem in context: if event == "end" and elem.tag == "record": ... process record elements ... root.clear() 

(в будущих версиях будет проще получить доступ к корневому элементу из цикла)

  • Стратегия ElementTree iterparse
  • Как быстро вывести XML-вывод из Python
  • Разбор XML - ElementTree vs SAX и DOM
  • Разбор большого RDF в Python
  • Одновременная обработка SAX больших, простых XML-файлов?
  •  
    Interesting Posts for Van-Lav

    как разделить список на n равных частей, python

    web2py db не определен

    Почему время python имеет 61 секунду

    Перемещение неперекрывающегося окна в Numpy

    Опасный Python Ключевые слова?

    Каковы преимущества использования метаклассов в реализациях, похожих на джанго?

    Почему мой обработчик click ttk.Treeview возвращает неправильный элемент в tree.focus ()?

    Внутри класса декоратора, экземпляр доступа класса, который содержит декорированный метод

    Использование модуля openpyxl для записи в электронную таблицу создает поврежденную электронную таблицу, как исправить с помощью zipfile-модуля?

    Асинхронные запросы блокировки торнадо

    Как получить номер строки в dataframe в Pandas?

    Как я могу использовать класс C ++ в Python?

    Python Запись в текстовый файл Словарь Показывает неправильную информацию

    Метод python __init__ в унаследованном классе

    Как удалить кнопку «Добавить» в администраторе Django для конкретной модели?

    Python - лучший язык программирования в мире.