Pourquoi est-ce que je vois "TypeError: les indices de chaîne doivent être des entiers"?

219

Je joue à la fois avec l'apprentissage de python et j'essaie d'obtenir des problèmes de github sous une forme lisible. Utilisation des conseils sur Comment puis-je convertir JSON en CSV? Je suis venu avec ceci:

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"]])

Où "issues.json" est le fichier json contenant mes problèmes github. Quand j'essaye de faire ça, je reçois

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

Qu'est-ce que j'oublie ici? Quels sont les "indices de chaîne"? Je suis sûr qu'une fois que cela fonctionnera, j'aurai plus de problèmes, mais pour l'instant, j'aimerais simplement que cela fonctionne!

Quand je modifie la fordéclaration pour simplement

for item in data:
    print item

ce que j'obtiens c'est ... "des problèmes" - donc je fais quelque chose de plus fondamentalement erroné. Voici un peu de mon 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...

quand j'imprime, dataon dirait que ça devient très bizarre:

{u'issues': [{u'body': u'Add missing paging (Older>>) lin...
Amanda
la source
Ce qui vous manque, c'est print repr(data)ouimport pprint; pprint.pprint(data)
John Machin

Réponses:

116

itemest très probablement une chaîne dans votre code; les indices de chaîne sont ceux entre crochets, par exemple gravatar_id. Je vérifierais donc d'abord votre datavariable pour voir ce que vous y avez reçu; Je suppose que datac'est une liste de chaînes (ou au moins une liste contenant au moins une chaîne) alors que ce devrait être une liste de dictionnaires.

Tamás
la source
159

La variable itemest une chaîne. Un index ressemble à ceci:

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

L'exemple ci-dessus utilise le 0 index de la chaîne pour faire référence au premier caractère.

Les chaînes ne peuvent pas avoir d'index de chaînes (comme les dictionnaires). Donc ça ne marchera pas:

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

dataest un dictobjet. Donc, parcourez-le comme ceci:

Python 2

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

Python 3

for key, value in data.items():
    print(key, value)
John Machin
la source
36

TypeError for Slice Notation str[a:b]

tl; dr: utilisez deux points : au lieu d'une virgule entre les deux indices aet bdansstr[a:b]


Lorsque vous travaillez avec des chaînes et une notation de tranche (une opération de séquence courante ), il peut arriver que a TypeErrorsoit élevé, soulignant que les indices doivent être des entiers, même s'ils le sont évidemment.

Exemple

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

Nous avons évidemment passé deux entiers pour les indices à la notation de tranche, non? Alors quel est le problème ici?

Cette erreur peut être très frustrante - en particulier au début de l'apprentissage de Python - car le message d'erreur est un peu trompeur.

Explication

Nous avons implicitement passé un tuple de deux entiers (0 et 5) à la notation de tranche lorsque nous avons appelé my_string[0,5]parce que 0,5(même sans les parenthèses) correspond au même tuple que ce (0,5)serait le cas.

Une virgule ,suffit en fait à Python pour évaluer quelque chose en tant que tuple:

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

Donc, ce que nous avons fait là-bas, cette fois explicitement:

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

Maintenant, au moins, le message d'erreur est logique.

Solution

Nous devons remplacer la virgule , par deux points : pour séparer correctement les deux entiers:

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

Un message d'erreur plus clair et plus utile aurait pu être quelque chose comme:

TypeError: string indices must be integers (not tuple)

Un bon message d'erreur indique directement à l'utilisateur ce qu'il a fait de mal et il aurait été plus évident de savoir comment résoudre le problème.

[Donc, la prochaine fois que vous vous retrouvez responsable de la rédaction d'un message de description d'erreur, pensez à cet exemple et ajoutez la raison ou d'autres informations utiles au message d'erreur pour que vous et peut-être d'autres personnes compreniez ce qui s'est passé.]

Leçons apprises

  • la notation par tranche utilise des deux-points :pour séparer ses indices (et la plage de pas, par exemple str[from:to:step])
  • les tuples sont définis par des virgules ,(par exemple t = 1,)
  • ajouter des informations aux messages d'erreur pour que les utilisateurs comprennent ce qui s'est mal passé


Bravo et bonne programmation winklerrr


[Je sais que cette question a déjà été répondue et ce n'était pas exactement la question posée par le démarreur de fil, mais je suis venu ici en raison du problème ci-dessus qui conduit au même message d'erreur. Au moins, il m'a fallu un certain temps pour trouver cette petite faute de frappe.

J'espère donc que cela aidera quelqu'un d'autre qui est tombé sur la même erreur et leur fait gagner du temps en trouvant cette minuscule erreur.]

winklerrr
la source
1

J'ai eu un problème similaire avec Pandas, vous devez utiliser la fonction iterrows () pour parcourir une documentation Pandas de jeu de données Pandas pour iterrows

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

notez que vous devez gérer l'index dans l'ensemble de données qui est également renvoyé par la fonction.

coremonkey
la source
0

Cela peut se produire si une virgule est manquante. Je suis tombé dessus quand j'ai eu une liste de deux tuples, dont chacun consistait en une chaîne en première position et une liste en deuxième. J'ai omis par erreur la virgule après le premier composant d'un tuple dans un cas, et l'interprète a pensé que j'essayais d'indexer le premier composant.

dumbledad
la source