guardar - leer json python
¿Cómo uso el módulo ''json'' para leer en un objeto JSON a la vez? (3)
Tengo un archivo JSON multi-gigabyte. El archivo está formado por objetos JSON que no son más que unos pocos miles de caracteres, pero no hay saltos de línea entre los registros.
Con Python 3 y el módulo json
, ¿cómo puedo leer un objeto JSON a la vez desde el archivo a la memoria?
Los datos están en un archivo de texto plano. Aquí hay un ejemplo de un registro similar. Los registros reales contienen muchos diccionarios y listas anidadas.
Grabar en formato legible:
{
"results": {
"__metadata": {
"type": "DataServiceProviderDemo.Address"
},
"Street": "NE 228th",
"City": "Sammamish",
"State": "WA",
"ZipCode": "98074",
"Country": "USA"
}
}
}
Formato actual. Los nuevos registros comienzan uno tras otro sin interrupciones.
{"results": { "__metadata": {"type": "DataServiceProviderDemo.Address"},"Street": "NE 228th","City": "Sammamish","State": "WA","ZipCode": "98074","Country": "USA" } } }{"results": { "__metadata": {"type": "DataServiceProviderDemo.Address"},"Street": "NE 228th","City": "Sammamish","State": "WA","ZipCode": "98074","Country": "USA" } } }{"results": { "__metadata": {"type": "DataServiceProviderDemo.Address"},"Street": "NE 228th","City": "Sammamish","State": "WA","ZipCode": "98074","Country": "USA" } } }
Aquí hay una pequeña modificación de la solución de Martijn Pieters , que manejará cadenas JSON separadas con espacios en blanco.
def json_parse(fileobj, decoder=json.JSONDecoder(), buffersize=2048,
delimiters=None):
remainder = ''''
for chunk in iter(functools.partial(fileobj.read, buffersize), ''''):
remainder += chunk
while remainder:
try:
stripped = remainder.strip(delimiters)
result, index = decoder.raw_decode(stripped)
yield result
remainder = stripped[index:]
except ValueError:
# Not enough data to decode, read more
break
Por ejemplo, si data.txt
contiene cadenas JSON separadas por un espacio:
{"business_id": "1", "Accepts Credit Cards": true, "Price Range": 1, "type": "food"} {"business_id": "2", "Accepts Credit Cards": true, "Price Range": 2, "type": "cloth"} {"business_id": "3", "Accepts Credit Cards": false, "Price Range": 3, "type": "sports"}
entonces
In [47]: list(json_parse(open(''data'')))
Out[47]:
[{u''Accepts Credit Cards'': True,
u''Price Range'': 1,
u''business_id'': u''1'',
u''type'': u''food''},
{u''Accepts Credit Cards'': True,
u''Price Range'': 2,
u''business_id'': u''2'',
u''type'': u''cloth''},
{u''Accepts Credit Cards'': False,
u''Price Range'': 3,
u''business_id'': u''3'',
u''type'': u''sports''}]
En términos generales, colocar más de un objeto JSON en un archivo hace que ese archivo no sea válido, JSON dañado . Dicho esto, aún puede analizar datos en fragmentos utilizando el método JSONDecoder.raw_decode()
.
Lo siguiente producirá objetos completos a medida que el analizador los encuentre:
from json import JSONDecoder
from functools import partial
def json_parse(fileobj, decoder=JSONDecoder(), buffersize=2048):
buffer = ''''
for chunk in iter(partial(fileobj.read, buffersize), ''''):
buffer += chunk
while buffer:
try:
result, index = decoder.raw_decode(buffer)
yield result
buffer = buffer[index:]
except ValueError:
# Not enough data to decode, read more
break
Esta función leerá fragmentos del objeto de archivo dado en trozos de buffersize
, y buffersize
que el objeto decoder
buffersize
objetos JSON completos del búfer. Cada objeto analizado se cede al llamante.
Úsalo así:
with open(''yourfilename'', ''r'') as infh:
for data in json_parse(infh):
# process object
Use esto solo si sus objetos JSON están escritos en un archivo consecutivo, sin nuevas líneas entre ellos. Si tiene líneas nuevas y cada objeto JSON está limitado a una sola línea, tiene un documento de líneas JSON , en cuyo caso puede usar Cargar y analizar un archivo JSON con varios objetos JSON en Python .
Si sus documentos JSON contienen una lista de objetos, y desea leer un objeto a la vez, puede usar el analizador iterativo JSON ijson para el trabajo. Solo leerá más contenido del archivo cuando necesite decodificar el siguiente objeto.
Tenga en cuenta que debe usarlo con la biblioteca YAJL , de lo contrario probablemente no verá ningún aumento de rendimiento.
Dicho esto, a menos que su archivo sea realmente grande , leerlo completamente en la memoria y luego analizarlo con el módulo JSON normal probablemente seguirá siendo la mejor opción.