Quel est le moyen le plus rapide pour analyser de grandes XML docs en Python?
Je suis en train d'exécuter le code suivant fondée sur le Chapitre 12.5 du 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
Je suis en train de travailler avec des documents XML d'environ 1 GO en taille. Quelqu'un sait-il un moyen plus rapide pour analyser ces?
- Votre question est beaucoup trop vague pour glaner toutes les réponses utiles. Envisager de répondre à ces questions: - Qu'essayez-vous de faire avec ce 1 GO de document XML? - À quelle vitesse avez-vous besoin de cet analyseur être? - Pourriez-vous paresseusement parcourir le document, plutôt que de se charger de tout ce qui est dans la mémoire de l'aller?
- J'ai besoin de charger en mémoire, l'index, les données, puis "parcourir", et de la traiter.
Vous devez vous connecter pour publier un commentaire.
Je me semble que si vous n'avez pas besoin DOM capacités de votre programme. Je voudrais deuxième l'utilisation de l' (c)ElementTree de la bibliothèque. Si vous utilisez le iterparse fonction de la cElementTree module, vous pouvez travailler votre chemin à travers le xml et de traiter les événements comme ils se produisent.
Noter, cependant, Fredriks conseils sur l'utilisation de cElementTree iterparse fonction:
La lxml.iterparse() ne le permet pas.
La précédente ne fonctionne pas sur Python 3.7, envisager de la façon suivante pour obtenir le premier élément.
Avez-vous essayé Le cElementTree Module?
cElementTree est fourni avec Python 2.5 et plus tard, comme xml.programme etree.cElementTree. Reportez-vous à la repères.
retiré morts ImageShack lien
Je vous recommande d'utiliser lxml, c'est un binding python pour la bibliothèque libxml2 qui est vraiment très rapide.
Dans mon expérience, libxml2 et les expatriés ont très similaire à la performance. Mais je préfère libxml2 (et lxml pour python), car il semble être plus activement développé et testé. Aussi libxml2 a plus de fonctionnalités.
lxml est principalement API compatible avec xml.programme etree.ElementTree. Et il y a une bonne documentation sur son site web.
Enregistrer les callbacks ralentit l'analyse énormément. [EDIT]C'est parce que le (rapide) du code C a pour invoquer l'interpréteur python qui n'est tout simplement pas aussi vite que C. Fondamentalement, vous utilisez le code C pour lire le fichier (rapide) et ensuite construire le DOM en Python (lent).[/EDIT]
Essayez d'utiliser xml.programme etree.ElementTree qui est mis en œuvre à 100% en C et qui peut analyser XML, sans les rappels de code python.
Après que le document a été analysé, vous pouvez le filtrer pour obtenir ce que vous voulez.
Si c'est encore trop lent et vous n'avez pas besoin d'un DOM à l'autre option est de lire le fichier en une chaîne de caractères et utiliser de simples opérations de la chaîne à traiter.
Si votre demande est des performances sensibles et susceptibles de rencontrer de gros fichiers (comme vous l'avez dit, > 1 GO) alors que j'avais fortement vous déconseillons d'utiliser le code dont vous faites preuve dans votre question, pour la simple raison que il charge l'intégralité du document dans la mémoire vive. Je vous encourage à repenser votre dessin (si possible) pour éviter de tenir l'ensemble de l'arborescence du document dans la mémoire RAM à la fois. Ne sachant pas ce que les exigences de votre application sont, je ne peux pas correctement suggérer une approche spécifique, autre que le générique morceau de conseils pour essayer d'utiliser un "événement" basée sur la conception.
expat ParseFile fonctionne bien si vous n'avez pas besoin de stocker la totalité de l'arbre dans la mémoire, qui sera tôt ou tard exploser votre RAM pour les gros fichiers:
Il lit les fichiers en morceaux, et les nourrit à l'analyseur sans exploser de RAM.
Doc: https://docs.python.org/2/library/pyexpat.html#xml.parsers.expat.xmlparser.ParseFile
Apparemment PyRXP est vraiment très rapide.
Ils prétendent qu'il est le plus rapide de l'analyseur, mais cElementTree n'est pas dans leur stats liste.
J'ai passé assez de temps à essayer cela et il semble que la manière la plus rapide et la moins gourmande en mémoire l'approche est à l'aide de lxml et iterparse, mais en s'assurant de libérer la mémoire non. Dans mon exemple, l'analyse arXiv dump:
Donc
element.clear
n'est pas assez, mais également la suppression de tous les liens vers les éléments précédents.