json KeyError con json.loads

JSON parece estar hipo en las siguientes afirmaciones:

{"delete":{"status":{"id":12600579001,"user_id":55389449}}} 

fragmento de código:

 temp = json.loads(line) text = temp['text'] 

Obtengo la siguiente salida de error cuando el fragmento de código anterior encuentra líneas similares al ‘diccionario’ JSON anterior:

 text = temp['text'] KeyError: 'text' 

¿Es porque no hay una clave de “texto” en la línea o porque “eliminar” no está en el diccionario?

¿Es porque no hay una clave de “texto” en la línea o porque “eliminar” no está en el diccionario?

Es porque no hay una clave de “texto”. Si print temp o comprueba si la clave 'text' está en el diccionario de Python resultante, notará que no hay ninguna clave llamada 'text' . De hecho, temp solo tiene una tecla: 'delete' . El diccionario al que se hace referencia por 'delete' contiene una sola clave 'status' que contiene otro diccionario con dos claves: 'user_id' e 'id' .

En otras palabras, su estructura es esta:

 { "delete" : { "status" : { "id" : 12600579001, "user_id" : 55389449 } } } 

Como puede ver, no hay ninguna tecla de “texto” en ninguna parte.

Además, puedes comprobarlo tú mismo:

 >>> 'text' in temp False >>> 'delete' in temp True 

Parece que esto sucede porque el ‘texto’ no está ahí. Tal vez podrías usar algo como

 'text' in temp 

para comprobar que el ‘texto’ existe antes de intentar usarlo.

Editar:

Tomé el ejemplo dado en el comentario y le agregué un bloque if / elif / else.

 #! /usr/bin/python import sys import json f = open(sys.argv[1]) for line in f: j = json.loads(line) try: if 'text' in j: print 'TEXT: ', j['text'] elif 'delete' in j: print 'DELETE: ', j['delete'] else: print 'Everything: ', j except: print "EXCEPTION: ", j 

Muestra Chunk # 1:

{u’favorited ‘: False, u’contributors’: Ninguno, u’truncated ‘: False, u’text’: —- snip —-}

Muestra Chunk # 2:

{u’delete ‘: {u’status’: {u’user_id ‘: 55389449, u’id’: 12600579001L}}}

Desde el fragmento que publicaste, parece que temp solo debería tener un elemento, con la tecla "delete" . No tiene un 'text' clave, por lo que no estoy seguro de qué temp['text'] debería buscar.

Intenta esto para ver el problema en detalle:

 import json line = '{"delete":{"status":{"id":12600579001,"user_id":55389449}}}' print 'line:', line temp = json.loads(line) print 'temp:', json.dumps(temp, indent=4) print 'keys in temp:', temp.keys() 

Lo que genera esta salida:

 line: {"delete":{"status":{"id":12600579001,"user_id":55389449}}} temp: { "delete": { "status": { "user_id": 55389449, "id": 12600579001 } } } keys in temp: [u'delete'] 

La única clave en el dictado temp es ‘eliminar’. Por lo tanto, temp['text'] genera un KeyError.

¿Por qué no poner esto entre la primera y la segunda línea?

 print temp 

inténtalo así:

  temp = json.load(line) for lines in temp text = lines['text'] 

Gracias a todos por las sugerencias. El núcleo del problema era que el formato json de Twitter tiene un diccionario dentro de un diccionario. La solución implica un índice doble para obtener las variables que debo comprobar.

 #!/usr/bin/env python import sys import json from pprint import pprint json_file=sys.argv[1] json_data=open(json_file) j = json.load(json_data) def main(): for attribute_key in j['root_attribute']: try: print attribute_key['name'], attribute_key['status'], attribute_key['text'] except KeyError: pass if __name__ == "__main__": main() 

use dict.get (clave [, predeterminado]) si hay un caso válido cuando falta la clave: temp.get('text') lugar de temp['text'] no lanzará una excepción, pero devolverá Null si el no se encuentra la clave.

EAFP (Más fácil pedir perdón que permiso) es más Pythonic que LBYL (Mira antes de saltar).