Forma eficiente de analizar XML en ElementTree (1.3.0) Python

Estoy tratando de analizar un enorme archivo XML que va desde (20MB-3GB). Los archivos son muestras procedentes de diferentes Instrumentación. Entonces, lo que estoy haciendo es encontrar la información necesaria del elemento del archivo e insertarla en la base de datos (Django).

Pequeña parte de mi archivo de muestra. El espacio de nombres existe en todos los archivos. Una característica interesante de los archivos es que tienen más atributos de nodo que texto.

                   

Archivo pequeño pero completo aquí

Entonces, lo que he hecho hasta ahora es usar findall para cada elemento de interés.

 import xml.etree.ElementTree as ET tree=ET.parse('plgs_example.mzML') root=tree.getroot() NS="{http://psi.hupo.org/ms/mzml}" s=tree.findall('.//{http://psi.hupo.org/ms/mzml}instrumentConfiguration') for ins in range(len(s)): insattrib=s[ins].attrib # It will print out all the id attribute of instrument print insattrib["id"] 

¿Cómo puedo acceder a todos los hijos / nietos del elemento instrumentFiguration (s)?

 s=tree.findall('.//{http://psi.hupo.org/ms/mzml}instrumentConfiguration') 

Ejemplo de lo que quiero

 InstrumentConfiguration ----------------------- Id:QTOF Parameter1: T-Tof ultima source:nanoelectrospray analyzer: quadrupole analyzer: time-of-flight detector: microchannel plate decector 

¿Existe una forma eficiente de analizar el elemento / subelemento / subelemento cuando existe el espacio de nombres? ¿O tengo que usar find / findall cada vez para acceder a un elemento en particular en el árbol con espacio de nombres? Este es solo un pequeño ejemplo que tengo que analizar una jerarquía de elementos más complejos.

¡Alguna sugerencia!

Editar

No obtuve la respuesta correcta, así que debes editar una vez más.

Related of "Forma eficiente de analizar XML en ElementTree (1.3.0) Python"

Aquí hay un script que analiza un millón de elementos de (archivo de 967MB ) en 40 segundos (en mi máquina) sin consumir una gran cantidad de memoria.

El rendimiento es de 24MB/s . La cElementTree page (2005) reporta 47MB/s .

 #!/usr/bin/env python from itertools import imap, islice, izip from operator import itemgetter from xml.etree import cElementTree as etree def parsexml(filename): it = imap(itemgetter(1), iter(etree.iterparse(filename, events=('start',)))) root = next(it) # get root element for elem in it: if elem.tag == '{http://psi.hupo.org/ms/mzml}instrumentConfiguration': values = [('Id', elem.get('id')), ('Parameter1', next(it).get('name'))] # cvParam componentList_count = int(next(it).get('count')) for parent, child in islice(izip(it, it), componentList_count): key = parent.tag.partition('}')[2] value = child.get('name') assert child.tag.endswith('cvParam') values.append((key, value)) yield values root.clear() # preserve memory def print_values(it): for line in (': '.join(val) for conf in it for val in conf): print(line) print_values(parsexml(filename)) 

Salida

 $ /usr/bin/time python parse_mxml.py Id: QTOF Parameter1: Q-Tof ultima source: nanoelectrospray analyzer: quadrupole analyzer: time-of-flight detector: microchannel plate detector 38.51user 1.16system 0:40.09elapsed 98%CPU (0avgtext+0avgdata 23360maxresident)k 1984784inputs+0outputs (2major+1634minor)pagefaults 0swaps 

Nota: el código es frágil , asume que los dos primeros hijos de son y y todos los valores están disponibles como nombres de etiqueta o atributos.

En el rendimiento

ElementTree 1.3 es ~ 6 veces más lento que cElementTree 1.0.6 en este caso.

Si reemplaza root.clear() por elem.clear() entonces el código es ~ 10% más rápido pero ~ 10 veces más memoria. lxml.etree funciona con la variante elem.clear() , el rendimiento es el mismo que para cElementTree pero consume 20 ( root.clear() ) / 2 ( elem.clear() ) veces más memoria (500MB).

Si esto sigue siendo un problema actual, puede probar pymzML, una interfaz de python para archivos mzML. Sitio web: http://pymzml.github.com/

En este caso, me gustaría encontrar findall para encontrar todos los elementos instrumentList. Luego, en esos resultados solo tiene que acceder a los datos como si instrumentList e instrument fueran arreglos, usted obtiene todos los elementos y no tiene que buscarlos todos.

Si sus archivos son enormes, eche un vistazo a la función iterparse() . Asegúrese de leer este artículo del autor de elementtree, especialmente la parte sobre “análisis incremental”.

Sé que esto es antiguo, pero me encuentro con este problema al hacer el análisis XML, donde mis archivos XML eran realmente grandes.

La respuesta de JF Sebastian es correcta, pero surgió el siguiente problema.

Lo que noté, es que a veces los valores en elem.text (si tiene valores dentro de XML y no como atributos) no se leen correctamente (a veces se devuelve Ninguno) si se itera a través de los atributos de inicio. Tuve que recorrer el ‘final’ así.

 it = imap(itemgetter(1), iter(etree.iterparse(filename, events=('end',)))) root = next(it) # get root element 

Si alguien quiere obtener el texto dentro de una etiqueta xml (y no un atributo) tal vez debería iterar a través de los eventos ‘finales’ y no ‘comenzar’.

Sin embargo, si todos los valores están en atributos, entonces el código en la respuesta de JF Sebastian es más correcto.

Ejemplo de XML para mi caso:

   Liechtenstein 1 2008 141100   Singapore 4 2011 59900   Panama 68 2011 13600