¿Alguien sabe de una forma eficiente de memoria para generar archivos xml muy grandes (por ejemplo, 100-500 MiB) en Python?¿Generar archivos XML muy grandes en Python?
He estado utilizando lxml, pero el uso de memoria está por las nubes.
¿Alguien sabe de una forma eficiente de memoria para generar archivos xml muy grandes (por ejemplo, 100-500 MiB) en Python?¿Generar archivos XML muy grandes en Python?
He estado utilizando lxml, pero el uso de memoria está por las nubes.
¿Tal vez podría utilizar un motor de plantillas en lugar de generar/construir el xml usted mismo?
Genshi por ejemplo está basado en xml y es compatible con la salida de transmisión. Un ejemplo muy básico:
from genshi.template import MarkupTemplate
tpl_xml = '''
<doc xmlns:py="http://genshi.edgewall.org/">
<p py:for="i in data">${i}</p>
</doc>
'''
tpl = MarkupTemplate(tpl_xml)
stream = tpl.generate(data=xrange(10000000))
with open('output.xml', 'w') as f:
stream.render(out=f)
Puede llevar un tiempo, pero el uso de la memoria sigue siendo bajo.
El mismo ejemplo para el motor Mako de plantillas (no xml "nativa"), pero mucho más rápido:
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)
El último ejemplo corrió en mi portátil durante unos 20 segundos, produciendo una (la verdad es muy simple) 151 MB de archivo xml, sin problemas de memoria.(de acuerdo con el administrador de tareas de Windows se mantuvo constante en aproximadamente 10MB)
Dependiendo de sus necesidades, esta podría ser una forma más amigable y más rápida de generar xml que usar SAX, etc. Consulte los documentos para ver qué puede hacer con estos motores (hay otros también, acabo de elegir estos dos como ejemplos)
¡Fantástica idea! Este es definitivamente uno que vale la pena considerar. –
La única forma sensata de generar un archivo XML tan grande es línea por línea, lo que significa imprimir mientras se ejecuta una máquina de estado, y lotes de prueba.
Gracias por la respuesta. SAX ftl .. argh ... –
Obviamente, debe evitar tener que construir todo el árbol (ya sea DOM o etree o lo que sea) en la memoria. Pero la mejor manera depende de la fuente de sus datos y de cuán complicada e interrelacionada es la estructura de su salida.
Si es grande porque tiene miles de instancias de elementos bastante independientes, puede generar el contenedor externo y luego generar árboles para cada elemento y luego serializar cada fragmento a la salida.
Si los fragmentos no son tan independientes, entonces tendrá que hacer algunos registros adicionales, como administrar una base de datos de ids generados & idrefs.
Lo dividiría en 2 o 3 partes: un productor de eventos de saxo, un serializador de salida comiendo eventos de saxo, y opcionalmente, si parece más fácil trabajar con algunas piezas independientes como objetos o árboles, algo para construir esos objetos y luego convertirlos en eventos de saxo para el serializador.
Tal vez podría simplemente administrarlo todo como salida de texto directo, en lugar de lidiar con eventos de saxo: eso depende de cuán complicado sea.
Este también puede ser un buen lugar para usar generadores de pitón como una forma de transmitir la salida sin tener que construir grandes estructuras en la memoria.
Hmm, sí, tendrá miles de instancias de elementos bastante independientes. Creo que podría ese enfoque. Gracias. –
El método de plantillas sugerido anteriormente es probablemente más fácil, especialmente si los objetos/trozos separados son lo suficientemente pequeños como para manipularlos. Ejecutar el par de productor/consumidor de SAX como co-rutinas usando generadores de pitón sería la alternativa si las cosas no se dividieran fácilmente en trozos suficientemente pequeños. –
Si su documento es muy regular (como un grupo de registros de bases de datos, todos en el mismo formato) podría usar mi propia biblioteca "xe".
http://home.avvanta.com/~steveha/xe.html
La biblioteca xe fue diseñado para generar alimentos sindicación (Atom, RSS, etc.) y creo que es fácil de usar. Necesito actualizarlo para Python 2.6, y aún no lo siento, lo siento.
Muy agradable. ¿Es esto más eficiente en cuanto a la memoria que usar lxml? –
No estoy seguro. No he visto lxml todavía. Si mantiene todos sus datos a la vez, entonces tiene al menos 500 MiB sin importar nada. Pero si está escribiendo cosas en un bucle, podría volver a utilizar las mismas estructuras de datos xe, lo que ahorraría memoria. ¿Pero tal vez podrías hacer lo mismo con lxml? – steveha
¿Es esta una buena idea? ¿Qué va a * consumir * un archivo así? –
500MiB archivo XML? Yikes: si mis archivos XML llegaran a 500MiB, consideraría un formato de archivo más eficiente. :-) –
No por elección, confíe en mí :) –