Lectura eficiente de un archivo XML de 800 GB en Python 2.7

Estoy leyendo un archivo xml de 800 GB en Python 2.7 y lo estoy analizando con un analizador iterativo etree.

Actualmente, solo uso open('foo.txt') sin argumento de almacenamiento en búfer. Estoy un poco confundido si este es el enfoque que debo tomar o si debo usar un argumento de almacenamiento en búfer o usar algo de io como io.BufferedReader o io.open o io.TextIOBase.

Un punto en la dirección correcta sería muy apreciado.

La función estándar open() ya, de manera predeterminada, devuelve un archivo en búfer (si está disponible en su plataforma). Para los objetos de archivo que normalmente está completamente almacenado en búfer.

Generalmente aquí significa que Python deja esto a la implementación de C stdlib; utiliza una llamada fopen() ( wfopen() en Windows para admitir los nombres de archivo UTF-16), lo que significa que se elige el búfer predeterminado para un archivo; En Linux creo que sería 8kb. Para una operación de lectura pura como el análisis XML, este tipo de almacenamiento en búfer es exactamente lo que desea.

El análisis XML realizado por iterparse lee el archivo en fragmentos de 16384 bytes (16kb).

Si desea controlar el tamaño de buffers, use el argumento de palabra clave de buffering :

 open('foo.xml', buffering=(2<<16) + 8) # buffer enough for 8 full parser reads 

que anulará el tamaño del búfer predeterminado (que esperaría que coincida con el tamaño del bloque de archivo o un múltiplo del mismo). De acuerdo con este artículo, boost el búfer de lectura debería ayudar, y usar un tamaño al menos 4 veces el tamaño de bloque de lectura esperado más 8 bytes mejorará el rendimiento de lectura. En el ejemplo anterior, lo puse en 8 veces el tamaño de lectura de ElementTree.

La función io.open() representa la nueva estructura de objetos de E / S de Python 3, donde la E / S se ha dividido en una nueva jerarquía de tipos de clases para ofrecerle más flexibilidad. El precio es más indirecto, más capas para que los datos tengan que viajar, y el código Python C hace más trabajo por sí solo en lugar de dejar eso al sistema operativo.

Puedes probar y ver si io.open('foo.xml', 'rb', buffering=2<<16) va a funcionar mejor. Abrir en modo rb te dará una instancia de io.BufferedReader .

No desea utilizar io.TextIOWrapper ; el analizador de expatriados subyacente desea datos en bruto, ya que decodificará su propia encoding XML. Sólo agregaría sobrecarga adicional; obtienes este tipo si abres en r (modo de texto) en su lugar.

El uso de io.open() puede brindarle más flexibilidad y una API más rica, pero el objeto de archivo C subyacente se abre con open() lugar de fopen() , y la implementación de Python io.BufferedIOBase controla todo el almacenamiento en búfer.

Tu problema será procesar esta bestia, no el archivo que se lee, creo. La memoria caché del disco se grabará prácticamente de todos modos al leer un archivo de 800 GB.

¿Has probado una función perezosa ?: ¿ Método perezoso para leer archivos grandes en Python?

Esto parece que ya responde a tu pregunta. Sin embargo, consideraría usar este método para escribir sus datos en una BASE DE DATOS, mysql es gratis: http://dev.mysql.com/downloads/ , NoSQL también es gratis y podría ser un poco más a la medida de las operaciones que implican escribir 800gb de datos, o cantidades similares: http://www.oracle.com/technetwork/database/nosqldb/downloads/default-495311.html

No lo he probado con tales archivos xml épicos, pero la última vez que tuve que tratar con archivos xml grandes (y relativamente simples), usé un analizador de saxofón .

Básicamente, le proporciona devoluciones de llamada para cada “evento” y le deja a usted almacenar los datos que necesita. Puede dar un archivo abierto para que no tenga que leerlo de una vez.