Perché vedo "TypeError: gli indici di stringa devono essere numeri interi"?


219

Sto giocando con l'apprendimento di Python e cercando di ottenere i problemi di github in una forma leggibile. Utilizzando i consigli su Come posso convertire JSON in CSV? Ho pensato a questo:

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","votes","created_at","comments","body","title","updated_at","html_url","user","labels","state"])

for item in data:
        csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])

Dove "issues.json" è il file json contenente i miei problemi con github. Quando provo a farlo, ottengo

File "foo.py", line 14, in <module>
csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])

TypeError: string indices must be integers

Cosa mi sto perdendo qui? Quali sono gli "indici di stringa"? Sono sicuro che una volta che avrò funzionato avrò più problemi, ma per ora, mi piacerebbe solo che funzionasse!

Quando modifico forsemplicemente l' affermazione

for item in data:
    print item

quello che ottengo è ... "problemi" - quindi sto facendo qualcosa di più sbagliato di base. Ecco un po 'del mio json:

{"issues":[{"gravatar_id":"44230311a3dcd684b6c5f81bf2ec9f60","position":2.0,"number":263,"votes":0,"created_at":"2010/09/17 16:06:50 -0700","comments":11,"body":"Add missing paging (Older>>) links...

quando datastampo sembra che si stia davvero stranendo:

{u'issues': [{u'body': u'Add missing paging (Older>>) lin...

Quello che ti manca è print repr(data)oimport pprint; pprint.pprint(data)
John Machin,

Risposte:


116

itemè molto probabilmente una stringa nel tuo codice; gli indici di stringa sono quelli tra parentesi quadre, ad es gravatar_id. Quindi prima controllo la tua datavariabile per vedere cosa hai ricevuto lì; Immagino che datasia un elenco di stringhe (o almeno un elenco contenente almeno una stringa) mentre dovrebbe essere un elenco di dizionari.


159

La variabile itemè una stringa. Un indice è simile al seguente:

>>> mystring = 'helloworld'
>>> print mystring[0]
'h'

L'esempio precedente utilizza l' 0indice della stringa per fare riferimento al primo carattere.

Le stringhe non possono avere indici di stringa (come i dizionari possono). Quindi questo non funzionerà:

>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers

42

dataè un dictoggetto. Quindi, iterate su di esso in questo modo:

Python 2

for key, value in data.iteritems():
    print key, value

Python 3

for key, value in data.items():
    print(key, value)

36

TypeError for Slice Notation str[a:b]

tl; dr: usa i due punti : anziché una virgola tra i due indici ae binstr[a:b]


Quando si lavora con stringhe e slice notation (un'operazione di sequenza comune ), può capitare che a TypeErrorsia sollevato, sottolineando che gli indici devono essere numeri interi, anche se ovviamente lo sono.

Esempio

>>> my_string = "hello world"
>>> my_string[0,5]
TypeError: string indices must be integers

Ovviamente abbiamo passato due numeri interi per gli indici alla notazione slice, giusto? Quindi qual è il problema qui?

Questo errore può essere molto frustrante, specialmente all'inizio dell'apprendimento di Python, perché il messaggio di errore è un po 'fuorviante.

Spiegazione

Abbiamo implicitamente passato una tupla di due numeri interi (0 e 5) alla notazione della sezione quando abbiamo chiamato my_string[0,5]perché 0,5(anche senza le parentesi) restituisce la stessa tupla che (0,5)farebbe.

In ,realtà una virgola è sufficiente per Python per valutare qualcosa come una tupla:

>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>

Quindi quello che abbiamo fatto lì, questa volta esplicitamente:

>>> my_string = "hello world"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers

Ora, almeno, il messaggio di errore ha un senso.

Soluzione

Dobbiamo sostituire la virgola , con due punti : per separare correttamente i due numeri interi:

>>> my_string = "hello world"
>>> my_string[0:5]
'hello'

Un messaggio di errore più chiaro e più utile avrebbe potuto essere qualcosa di simile:

TypeError: string indices must be integers (not tuple)

Un buon messaggio di errore mostra all'utente direttamente cosa ha fatto di sbagliato e sarebbe stato più ovvio come risolvere il problema.

[Quindi la prossima volta che ti ritroverai responsabile della scrittura di un messaggio di descrizione dell'errore, pensa a questo esempio e aggiungi il motivo o altre informazioni utili al messaggio di errore per consentire a te e forse ad altre persone di capire cosa è andato storto.]

Lezioni imparate

  • la notazione delle sezioni utilizza due punti :per separare i suoi indici (e intervallo di passi, ad es. str[from:to:step])
  • le tuple sono definite da virgole ,(ad es. t = 1,)
  • aggiungere alcune informazioni ai messaggi di errore affinché gli utenti possano capire cosa è andato storto

Saluti e buona programmazione
winklerrr


[So che a questa domanda è già stata data una risposta e questa non era esattamente la domanda posta dal thread iniziale, ma sono venuto qui a causa del problema sopra che porta allo stesso messaggio di errore. Almeno mi ci è voluto un po 'di tempo per trovare quel piccolo errore di battitura.

Quindi spero che questo possa aiutare qualcun altro che si è imbattuto nello stesso errore e che gli fa risparmiare un po 'di tempo nel trovare quel piccolo errore.]


1

Ho avuto un problema simile con Pandas, è necessario utilizzare la funzione iterrows () per scorrere una serie di dati Pandas Documentazione Pandas per iterrows

data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
    print('{} {}'.format(item["gravatar_id"], item["position"]))

si noti che è necessario gestire l'indice nel set di dati restituito anche dalla funzione.


0

Questo può accadere se manca una virgola. Mi sono imbattuto in esso quando avevo un elenco di due tuple, ognuna delle quali consisteva in una stringa nella prima posizione e in una lista nella seconda. Ho omesso erroneamente la virgola dopo il primo componente di una tupla in un caso, e l'interprete pensava che stessi cercando di indicizzare il primo componente.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.