11
votes

Générer de très grands fichiers XML à Python?

Quelqu'un peut-il connaître un moyen efficace de la mémoire de générer de très grands fichiers XML (par exemple 100-500 MIB) dans Python?

J'utilise lxml , mais l'utilisation de la mémoire est à travers le toit.


4 commentaires

Est-ce une bonne idée ? Qu'est-ce qui va consommer un tel fichier?


500MIB XML Fichier? Yikes - Si mes fichiers XML sont arrivés à 500mib, je considérerais un format de fichier plus efficace! :-)


Quelle est la complication du document de sortie? D'où obtenez-vous les données d'entrée? Quelle est la complication des transformations d'entrée-sortie?


Avez-vous envisagé de savoir si vous pouvez le casser en pièces plus gérables et utiliser Xinclude? Dépend, je suppose que sur quel type de processus va consommer ce gros fichier, car le problème ne serait pas de traiter le Xinclempt dans un fichier volumineux à la fin, mais d'avoir le processus de processus de consommation final le XIninclude à la volée . Je ne sais pas si ce modèle s'intégrerait dans votre flux de travail, mais si cela le faisait, cela pourrait le rendre plus gérable. (J'ai du mal à imaginer quel type de processus serait le consommateur d'un fichier XML de 500 Mo! ;-)


4 Réponses :


2
votes

Le seul moyen sensumé de générer un fichier XML si grand est la ligne par ligne, ce qui signifie une impression lors de l'exécution d'une machine à états et lots de tests.


0 commentaires

2
votes

Évidemment, vous devez éviter de devoir construire l'arborescence entier (DOM ou Etree ou autre) en mémoire. Mais la meilleure façon dépend de la source de vos données et de la manière compliquée et liée à la structure de votre sortie.

Si c'est grand, car il a des milliers d'instances d'objets assez indépendants, vous pouvez générer l'emballage externe, puis construire des arbres pour chaque élément, puis sérialiser chaque fragment à la sortie.

Si les fragments ne sont pas si indépendants, vous devrez alors faire une comptabilité supplémentaire - comme peut-être gérer une base de données d'IDS et de IDREFS générés.

Je le briserais dans 2 ou 3 parties: un producteur d'événement SAX, un sérialiseur de sortie Manger des événements saxoques, et éventuellement, s'il semble plus facile de travailler avec des éléments indépendants comme objets ou arbres, quelque chose à construire ces objets, puis à les transformer en événements saxoques pour le sérialisateur.

Peut-être que vous pourriez simplement gérer tout comme une sortie de texte direct, au lieu de traiter avec les événements SAX: cela dépend de la complication de la complication.

Ceci peut également être un bon endroit pour utiliser des générateurs Python comme moyen de diffuser la sortie sans avoir à construire de grandes structures en mémoire.


2 commentaires

HMM, oui, il aura des milliers d'instances d'articles assez indépendants. Je pense que je pourrais cette approche. Merci.


L'approche de modèles suggérée ci-dessus est probablement plus facile - surtout si les objets / morceaux distincts sont suffisamment petits pour manipuler. Exécution du producteur SAX / paire de consommateurs à mesure que les co-routines utilisant des générateurs Python seraient à l'alternative si les choses ne se sont pas facilement rompues dans de petits morceaux.




10
votes

Peut-être que vous pourriez utiliser un moteur de modèles au lieu de générer / construire le XML vous-même?

Genshi par exemple est basé sur XML et prend en charge la sortie en continu. Un exemple très fondamental: p> xxx pré>

Il peut prendre un certain temps, mais l'utilisation de la mémoire reste faible. P>

Le même exemple pour le MAKO Moteur de modèles (non" Nativement "XML), mais beaucoup plus vite: P>

from mako.template import Template
from mako.runtime import Context

tpl_xml = '''
<doc>
% for i in data:
<p>${i}</p>
% endfor
</doc>
'''

tpl = Template(tpl_xml)

with open('output.xml', 'w') as f:
    ctx = Context(f, data=xrange(10000000))
    tpl.render_context(ctx)


1 commentaires

Idée fantastique! Ceci est définitivement une valeur qui mérite d'être envisagée.