Что такое хороший анализатор потоков XML для Python? - PullRequest
8 голосов
/ 08 октября 2011

Существуют ли XML-парсеры для Python, которые могут анализировать потоки файлов? Мои XML-файлы слишком велики, чтобы уместиться в памяти, поэтому мне нужно проанализировать поток.

В идеале мне не нужно было бы иметь права root для установки, поэтому lxml не очень хороший вариант.

Я использовал xml.etree.ElementTree, но Я убежден, что он сломан .

Ответы [ 3 ]

13 голосов
/ 19 марта 2014

Вот хороший ответ о xml.etree.ElementTree.iterparse практике с огромными файлами XML.lxml также имеет метод.Ключом к анализу потока с помощью iterparse является ручная очистка и удаление уже обработанных узлов, поскольку в противном случае у вас закончится нехватка памяти.

Другой вариант - использование xml.sax.Официальное руководство слишком формально для меня, и в нем нет примеров, поэтому оно нуждается в разъяснении вместе с вопросом.Модуль синтаксического анализа по умолчанию, xml.sax.expatreader, реализует интерфейс инкрементального анализа xml.sax.xmlreader.IncrementalParser.То есть xml.sax.make_parser() предоставляет подходящий анализатор потока.

Например, для потока XML, например:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <entry><a>value 0</a><b foo='bar' /></entry>
  <entry><a>value 1</a><b foo='baz' /></entry>
  <entry><a>value 2</a><b foo='quz' /></entry>
  ...
</root>

Может обрабатываться следующим образом.

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import time
import xml.sax


class StreamHandler(xml.sax.handler.ContentHandler):

  lastEntry = None
  lastName  = None


  def startElement(self, name, attrs):
    self.lastName = name
    if name == 'entry':
      self.lastEntry = {}
    elif name != 'root':
      self.lastEntry[name] = {'attrs': attrs, 'content': ''}

  def endElement(self, name):
    if name == 'entry':
      print({
        'a' : self.lastEntry['a']['content'],
        'b' : self.lastEntry['b']['attrs'].getValue('foo')
      })
      self.lastEntry = None
    elif name == 'root':
      raise StopIteration

  def characters(self, content):
    if self.lastEntry:
      self.lastEntry[self.lastName]['content'] += content


if __name__ == '__main__':
  # use default ``xml.sax.expatreader``
  parser = xml.sax.make_parser()
  parser.setContentHandler(StreamHandler())
  # feed the parser with small chunks to simulate
  with open('data.xml') as f:
    while True:
      buffer = f.read(16)
      if buffer:
        try:
          parser.feed(buffer)
        except StopIteration:
          break
      else:
        time.sleep(2)
  # if you can provide a file-like object it's as simple as
  with open('data.xml') as f:
    parser.parse(f)
8 голосов
/ 08 октября 2011

Вы ищете xml.sax?Это прямо в стандартной библиотеке.

3 голосов
/ 08 октября 2011

Используйте xml.etree.cElementTree.Это намного быстрее, чем xml.etree.ElementTree.Ни один из них не сломан.Ваши файлы повреждены (см. Мой ответ на другой вопрос).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...