library leer extraer example etree datos con archivo python xml performance parsing

leer - xml python 3



¿Cuál es la forma más rápida de analizar grandes documentos XML en Python? (7)

Actualmente soy el siguiente código basado en el Capítulo 12.5 del Python Cookbook:

from xml.parsers import expat class Element(object): def __init__(self, name, attributes): self.name = name self.attributes = attributes self.cdata = '''' self.children = [] def addChild(self, element): self.children.append(element) def getAttribute(self,key): return self.attributes.get(key) def getData(self): return self.cdata def getElements(self, name=''''): if name: return [c for c in self.children if c.name == name] else: return list(self.children) class Xml2Obj(object): def __init__(self): self.root = None self.nodeStack = [] def StartElement(self, name, attributes): element = Element(name.encode(), attributes) if self.nodeStack: parent = self.nodeStack[-1] parent.addChild(element) else: self.root = element self.nodeStack.append(element) def EndElement(self, name): self.nodeStack.pop() def CharacterData(self,data): if data.strip(): data = data.encode() element = self.nodeStack[-1] element.cdata += data def Parse(self, filename): Parser = expat.ParserCreate() Parser.StartElementHandler = self.StartElement Parser.EndElementHandler = self.EndElement Parser.CharacterDataHandler = self.CharacterData ParserStatus = Parser.Parse(open(filename).read(),1) return self.root

Estoy trabajando con documentos XML de aproximadamente 1 GB de tamaño. ¿Alguien sabe una forma más rápida de analizar estos?


¿Has probado The cElementTree Module?

cElementTree se incluye con Python 2.5 y posterior, como xml.etree.cElementTree. Consulte los benchmarks .

eliminado el enlace muerto de ImageShack


Aparentemente, PyRXP es realmente rápido.

Afirman que es el analizador más rápido, pero cElementTree no está en su lista de estadísticas.


El registro de devoluciones de llamada ralentiza tremendamente el análisis. [EDITAR] Esto se debe a que el código C (rápido) tiene que invocar al intérprete python que simplemente no es tan rápido como C. Básicamente, estás usando el código C para leer el archivo (rápido) y luego compilar el DOM en Python (lento). [/ EDIT]

Intente utilizar xml.etree.ElementTree que se implementa al 100% en C y que puede analizar XML sin ninguna devolución de llamada al código python.

Una vez que se haya analizado el documento, puede filtrarlo para obtener lo que desea.

Si aún es demasiado lento y no necesita un DOM, otra opción es leer el archivo en una cadena y usar operaciones simples de cadena para procesarlo.


Me parece que no necesita ninguna capacidad DOM de su programa. Recomendaría el uso de la biblioteca (c) ElementTree. Si usa la función iterparse del módulo cElementTree, puede abrirse camino a través del xml y tratar los eventos a medida que ocurren.

Sin embargo, tenga en cuenta los consejos de Fredriks sobre el uso de la función cElementTree iterparse :

Para analizar archivos grandes, puede deshacerse de los elementos tan pronto como los haya procesado:

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

El patrón anterior tiene un inconveniente; no borra el elemento raíz, por lo que terminará con un elemento único con muchos elementos secundarios vacíos. Si sus archivos son enormes, en lugar de grandes, podría ser un problema. Para solucionar esto, debe tener en sus manos el elemento raíz. La forma más sencilla de hacerlo es habilitar eventos de inicio y guardar una referencia al primer elemento en una variable:

# 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()

El lxml.iterparse() no permite esto.


Si su aplicación es sensible al rendimiento y es probable que encuentre archivos de gran tamaño (como usted dijo,> 1GB), le recomiendo que no use el código que muestra en su pregunta por la simple razón de que carga todo el documento en la memoria RAM. . Le recomiendo que reconsidere su diseño (si es posible) para evitar tener todo el árbol de documentos en la memoria RAM de una vez. Sin saber cuáles son los requisitos de su aplicación, no puedo sugerir adecuadamente ningún enfoque específico, que no sea el consejo genérico para tratar de utilizar un diseño "basado en eventos".


Te recomiendo que uses lxml , es un enlace de python para la biblioteca libxml2 que es realmente rápido.

En mi experiencia, libxml2 y expat tienen un rendimiento muy similar. Pero prefiero libxml2 (y lxml para python) porque parece ser más activamente desarrollado y probado. También libxml2 tiene más funciones.

lxml es principalmente compatible con API con xml.etree.ElementTree . Y hay buena documentación en su sitio web.


expat ParseFile funciona bien si no necesita almacenar todo el árbol en la memoria, lo que tarde o temprano hará volar su RAM para archivos grandes:

import xml.parsers.expat parser = xml.parsers.expat.ParserCreate() parser.ParseFile(open(''path.xml'', ''r''))

Lee los archivos en fragmentos, y los alimenta al analizador sin explotar la RAM.

Doc: https://docs.python.org/2/library/pyexpat.html#xml.parsers.expat.xmlparser.ParseFile