2011-11-01 3 views
1

J'utilise python 2.7 avec la dernière librairie lxml. Je suis en train d'analyser un gros fichier XML avec une structure très homogène et des millions d'éléments. Je pensais que iterparse de lxml ne construirait pas un arbre interne pendant l'analyse, mais apparemment, il le fait depuis que l'utilisation de la mémoire augmente jusqu'à ce qu'elle se bloque (environ 1 Go). Existe-t-il un moyen d'analyser un grand fichier XML en utilisant lxml sans utiliser beaucoup de mémoire?L'analyse d'un fichier XML volumineux à l'aide de iterparse() consomme trop de mémoire. Toute alternative?

J'ai vu le target parser interface comme une possibilité, mais je ne suis pas sûr que cela fonctionnera mieux.

Répondre

2

Essayez d'utiliser Liza Daly fast_iter:

def fast_iter(context, func, args=[], kwargs={}): 
    # http://www.ibm.com/developerworks/xml/library/x-hiperfparse/ 
    # Author: Liza Daly 
    for event, elem in context: 
     func(elem, *args, **kwargs) 
     elem.clear() 
     while elem.getprevious() is not None: 
      del elem.getparent()[0] 
    del context 

fast_iter supprime des éléments d'arbre après qu'ils ont été analysés, ainsi que des éléments précédents (peut-être avec d'autres tags) qui ne sont plus nécessaires.

Il pourrait être utilisé comme ceci:

import lxml.etree as ET 
def process_element(elem): 
    ... 
context=ET.iterparse(filename, events=('end',), tag=...)   
fast_iter(context, process_element) 
+1

article Nice au lien. +1 –

+0

Il y a un gotcha avec le code de Liza; il attend des noms de tags uniques. Si vous avez le même tag imbriqué, alors le tag interne sera vide. (http://www.willmer.com/kb/2012/02/minor-gotcha-with-liza-dalys-fast_iter/ a une réponse un peu plus longue, ne peut pas trouver comment faire un exemple de code dans ce commentaire) – Rachel

+0

Rachel, je pense que le "gotcha" se produit si vous utilisez 'events = ('start',)' dans l'appel à 'ET.iterparse' et passez ce' context' à 'fast_iter'. Dans ce cas, les éléments sont supprimés lorsque la balise de début est atteinte plutôt que lorsque l'étiquette de fin est atteinte. Cela peut entraîner des erreurs (logiques ou syntaxiques). [Ce code ] (http://paste.ubuntu.com/829989/) montre le problème. Si c'est l'erreur que vous voyez, la solution est de changer 'start' à' end'. – unutbu

Questions connexes