¿Por qué veo "TypeError: los índices de cadenas deben ser números enteros"?
Estoy jugando con el aprendizaje de Python y estoy tratando de convertir los problemas de GitHub en un formato legible. Siguiendo los consejos sobre ¿Cómo puedo convertir JSON a CSV? , se me ocurrió esto:
import json
import csv
f = open('issues.json')
data = json.load(f)
f.close()
f = open("issues.csv", "wb+")
csv_file = csv.writer(f)
csv_file.writerow(["gravatar_id", "position", "number"])
for item in data:
csv_file.writerow([item["gravatar_id"], item["position"], item["number"]])
Donde "issues.json" es el archivo JSON que contiene mis problemas de GitHub. Cuando intento ejecutar eso, me sale
TypeError: string indices must be integers
¿Que me estoy perdiendo aqui? ¿Cuáles son los "índices de cadena"?
Aquí hay un poco de mi contenido JSON:
{"issues": [{"gravatar_id": "44230311a3dcd684b6c5f81bf2ec9f60", "position": 2.0, "number": 263...
La variable item
es una cadena. Un índice se parece a esto:
>>> mystring = 'helloworld'
>>> print mystring[0]
'h'
El ejemplo anterior utiliza el 0
índice de la cadena para referirse al primer carácter.
Las cadenas no pueden tener índices de cadena (como los diccionarios). Entonces esto no funcionará:
>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
item
Lo más probable es que sea una cadena en su código; los índices de cadena son los que están entre corchetes, por ejemplo, gravatar_id
. Así que primero verificaría tu data
variable para ver qué recibiste allí; Supongo que data
es una lista de cadenas (o al menos una lista que contiene al menos una cadena), mientras que debería ser una lista de diccionarios.
Error de tipo para notación de sectoresstr[a:b]
Respuesta corta
Utilice dos puntos :
en lugar de una coma ,
entre los dos índices a
y b
en str[a:b]
:
my_string[0,5] # wrong ❌
my_string[0:5] # correct ✅
Respuesta larga
Cuando se trabaja con cadenas y notación de corte (una operación de secuencia común ), puede suceder que TypeError
se eleve a, señalando que los índices deben ser números enteros, incluso si obviamente lo son.
Ejemplo
>>> my_string = "Hello, World!"
>>> my_string[0,5]
TypeError: string indices must be integers
Obviamente pasamos dos números enteros para los índices de la notación de corte, ¿verdad? Entonces, ¿cuál es el problema aquí?
Este error puede ser muy frustrante, especialmente al comienzo del aprendizaje de Python, porque el mensaje de error es un poco engañoso.
Explicación
Implícitamente pasamos tuple
dos enteros a la notación de segmento cuando llamamos my_string[0,5]
. 0,5
se evalúa como la misma tupla que (0,5)
lo hace, incluso sin los paréntesis. ¿Por qué sin embargo?
En realidad , una coma final ,
es suficiente para que el intérprete de Python evalúe algo como una tupla:
>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>
Entonces, lo que hicimos allí, esta vez explícitamente:
>>> my_string = "Hello, World!"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers
Ahora, al menos, el mensaje de error tiene sentido.
Solución
Necesitamos reemplazar la coma ,
con dos puntos :
para separar los dos números enteros correctamente, sin que se interpreten como tuple
:
>>> my_string = "Hello, World!"
>>> my_string[0:5]
'hello'
Un mensaje de error más claro y útil podría haber sido algo como:
TypeError: string indices must be integers not tuple
^^^^^
(actual type here)
¡Un buen mensaje de error debería mostrarle al usuario directamente qué hizo mal! Con este tipo de información habría sido mucho más fácil encontrar la causa raíz y resolver el problema, y no habría tenido que venir aquí.
Entonces, la próxima vez, cuando sea responsable de escribir mensajes de descripción de error, recuerde este ejemplo y agregue el motivo (u otra información útil) al mensaje de error. Ayude a otras personas (o tal vez incluso a su yo futuro) a comprender qué salió mal.
Lecciones aprendidas
- la notación de corte utiliza dos puntos
:
para separar sus índices (y rango de pasos, es decir,str[from:to:step]
) - las tuplas se definen mediante comas
,
(es decir,t = 1,
) - agregue información a los mensajes de error para que los usuarios comprendan qué salió mal
data
es un dict
objeto. Entonces, repítelo de esta manera:
Pitón 2
for key, value in data.iteritems():
print key, value
Pitón 3
for key, value in data.items():
print(key, value)
Tuve un problema similar con Pandas, necesitas usar la función iterrows() para iterar a través de un conjunto de datos de Pandas Documentación de Pandas para iterrows
data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
print('{} {}'.format(item["gravatar_id"], item["position"]))
tenga en cuenta que debe manejar el índice en el conjunto de datos que también devuelve la función.