Apertura de un archivo JSON grande en Python sin nuevas líneas para la conversión de csv Python 2.6.6

Estoy intentando convertir un archivo json muy grande a csv. He podido convertir un archivo pequeño de este tipo a un archivo csv de 10 registros (por ejemplo). Sin embargo, al intentar convertir un archivo grande (del orden de 50000 filas en el archivo csv) no funciona. Los datos fueron creados por un comando curl con la -o apuntando al archivo json que se creará. El archivo que se imprime no tiene caracteres de nueva línea. El archivo csv se escribirá con csv.DictWriter () y (donde los datos son la entrada del archivo json) tiene la forma

rowcount = len(data['MainKey']) colcount = len(data['MainKey'][0]['Fields']) 

Luego recorro el rango de las filas y columnas para obtener las entradas del diccionario csv

 csvkey = data['MainKey'][recno]['Fields'][colno]['name'] cvsval = data['MainKey'][recno][['Fields'][colno]['Values']['value'] 

Intenté usar las respuestas de otras preguntas, pero no funcionaron con un archivo grande ( du -m bigfile.json = 157 ) y los archivos que quiero manejar son aún más grandes.

Un bash de obtener el tamaño de cada línea muestra

 myfile = open('file.json','r'). line = readline(): print len(line) 

muestra que esto lee el archivo completo como una cadena completa. Por lo tanto, un archivo pequeño mostrará una longitud de 67744, mientras que un archivo más grande mostrará 163815116.

Un bash de leer los datos directamente de

 data=json.load(infile) 

Da el error que otras preguntas han discutido para los archivos grandes.

Un bash de usar el

 def json_parse(self, fileobj, decoder=JSONDecoder(), buffersize=2048): yield results 

como se muestra en otra respuesta , funciona con un archivo de 72 kb (10 filas, 22 columnas) pero parece bloquear o tomar una cantidad de tiempo interminable para un archivo de tamaño intermedio de 157 mb (de du -m bigfile.json)

Tenga en cuenta que una impresión de depuración muestra que cada fragmento tiene un tamaño de 2048 como lo especifica el argumento de entrada predeterminado. Parece que está tratando de pasar por todo el 163815116 (que se muestra en el len anterior) en 2048 trozos. Si cambio el tamaño del trozo a 32768, las matemáticas simples muestran que se necesitarían 5,000 ciclos en el ciclo para procesar el archivo.

Un cambio a un tamaño de trozo de 524288 sale del bucle aproximadamente cada 11 trozos, pero aún debe tomar aproximadamente 312 trozos para procesar el archivo completo

Si puedo hacer que se detenga al final de cada elemento de la fila, podré procesar esa fila y enviarla al archivo csv según el formulario que se muestra a continuación.

vi en el archivo pequeño muestra que es de la forma

 {"MainKey":[{"Fields":[{"Value": {'value':val}, 'name':'valname'}, {'Value': {'value':val}, 'name':'valname'}}], (other keys)},{'Fields' ... }] (other keys on MainKey level) } 

No puedo usar ijson ya que debo configurarlo para sistemas para los cuales no puedo importar software adicional.

Terminé usando un tamaño de trozo de 8388608 (0x800000 hex) para procesar los archivos. Luego procesé las líneas que se habían leído como parte del bucle, manteniendo el recuento de las filas procesadas y las filas descartadas. En cada función de proceso, agregué el número a los totales para poder realizar un seguimiento del total de registros procesados.

Esta parece ser la forma en que debe ir.

La próxima vez que se haga una pregunta como esta, enfatice que se debe especificar un tamaño de trozo grande y no el 2048 como se muestra en la respuesta original.

El bucle va

 first = True for data in self.json_parse(inf): records = len(data['MainKey']) columns = len(data['MainKey'][0]['Fields']) if first: # Initialize output as DictWriter ofile, outf, fields = self.init_csv(csvname, data, records, columns) first = False reccount, errcount = self.parse_records(outf, data, fields, records) 

Dentro de la rutina de análisis

 for rec in range(records): currec = data['MainKey'][rec] # If each column count can be different columns = len(currec['Fields']) retval, valrec = self.build_csv_row(currec, columns, fields) 

Para analizar las columnas use

 for col in columns: dataname = currec['Fields'][col]['name'] dataval = currec['Fields'][col]['Values']['value'] 

Por lo tanto, las referencias ahora funcionan y el procesamiento se maneja correctamente. Aparentemente, el segmento grande permite que el procesamiento sea lo suficientemente rápido para manejar los datos, mientras que es lo suficientemente pequeño para no sobrecargar el sistema.