Warum wird "TypeError: Zeichenfolgenindizes müssen Ganzzahlen sein" angezeigt?

219

Ich spiele sowohl mit dem Erlernen von Python als auch mit dem Versuch, Github-Probleme in eine lesbare Form zu bringen. Verwenden der Hinweise zu Wie kann ich JSON in CSV konvertieren? Ich habe mir das ausgedacht:

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

Wobei "Issues.json" die JSON-Datei ist, die meine Github-Probleme enthält. Wenn ich versuche, das auszuführen, bekomme ich

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

Was fehlt mir hier? Welches sind die "String-Indizes"? Ich bin mir sicher, dass ich, sobald ich das zum Laufen bringe, mehr Probleme haben werde, aber im Moment würde ich es einfach lieben, wenn das funktioniert!

Wenn ich die forAussage einfach ändere

for item in data:
    print item

Was ich bekomme ist ... "Probleme" - also mache ich etwas grundlegenderes falsch. Hier ist ein bisschen von meinem 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...

Wenn ich datadrucke, sieht es so aus, als würde es wirklich seltsam gemungert:

{u'issues': [{u'body': u'Add missing paging (Older>>) lin...
Amanda
quelle
Was Sie vermissen, ist print repr(data)oderimport pprint; pprint.pprint(data)
John Machin

Antworten:

116

itemist höchstwahrscheinlich eine Zeichenfolge in Ihrem Code; Die Zeichenfolgenindizes sind diejenigen in eckigen Klammern, z gravatar_id. Also würde ich zuerst Ihre dataVariable überprüfen , um zu sehen, was Sie dort erhalten haben. Ich denke, das dataist eine Liste von Zeichenfolgen (oder mindestens eine Liste, die mindestens eine Zeichenfolge enthält), während es eine Liste von Wörterbüchern sein sollte.

Tamás
quelle
158

Die Variable itemist eine Zeichenfolge. Ein Index sieht folgendermaßen aus:

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

Im obigen Beispiel wird der 0Index der Zeichenfolge verwendet, um auf das erste Zeichen zu verweisen.

Strings können keine String-Indizes haben (wie Wörterbücher). Das wird also nicht funktionieren:

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

dataist ein dictObjekt. Also iterieren Sie wie folgt darüber:

Python 2

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

Python 3

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

TypeError für die Slice-Notation str[a:b]

tl; dr: Verwenden Sie einen Doppelpunkt : anstelle eines Kommas zwischen den beiden Indizes aund binstr[a:b]


Bei der Arbeit mit Strings und Slice-Notation (eine häufige Sequenzoperation ) kann es vorkommen, dass a TypeErrorausgelöst wird, was darauf hinweist, dass die Indizes Ganzzahlen sein müssen, auch wenn dies offensichtlich der Fall ist.

Beispiel

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

Wir haben offensichtlich zwei ganze Zahlen für die Indizes an die Slice-Notation übergeben, oder? Was ist hier das Problem?

Dieser Fehler kann sehr frustrierend sein - insbesondere zu Beginn des Lernens von Python - da die Fehlermeldung etwas irreführend ist.

Erläuterung

Wir haben implizit ein Tupel aus zwei Ganzzahlen (0 und 5) an die Slice-Notation übergeben, als wir aufgerufen haben, my_string[0,5]weil 0,5(auch ohne die Klammern) dasselbe Tupel ausgewertet wird, wie dies der Fall (0,5)wäre.

Ein Komma ,reicht Python tatsächlich aus, um etwas als Tupel zu bewerten:

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

Also, was wir dort gemacht haben, diesmal explizit:

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

Zumindest jetzt macht die Fehlermeldung Sinn.

Lösung

Wir müssen das Komma , durch einen Doppelpunkt ersetzen :, um die beiden Ganzzahlen korrekt zu trennen:

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

Eine klarere und hilfreichere Fehlermeldung könnte wie folgt lauten:

TypeError: string indices must be integers (not tuple)

Eine gute Fehlermeldung zeigt dem Benutzer direkt, was er falsch gemacht hat, und es wäre offensichtlicher gewesen, wie das Problem gelöst werden könnte.

[Wenn Sie das nächste Mal für das Schreiben einer Fehlerbeschreibungsnachricht verantwortlich sind, denken Sie an dieses Beispiel und fügen Sie der Fehlermeldung den Grund oder andere nützliche Informationen hinzu, damit Sie und möglicherweise andere Personen verstehen, was schief gelaufen ist.]

Gewonnene Erkenntnisse

  • slice Notation verwendet Doppelpunkte :zu seinem Indizes (und Schrittbereich, zB zu trennen str[from:to:step])
  • Tupel werden definiert durch Kommata ,(z t = 1,)
  • Fügen Sie den Fehlermeldungen einige Informationen hinzu, damit Benutzer verstehen, was schief gelaufen ist

Prost und fröhliches Programmieren
winklerrr


[Ich weiß, dass diese Frage bereits beantwortet wurde und dies nicht genau die Frage war, die der Thread-Starter gestellt hat, aber ich bin wegen des obigen Problems hierher gekommen, das zu derselben Fehlermeldung führt. Zumindest habe ich einige Zeit gebraucht, um diesen kleinen Tippfehler zu finden.

Ich hoffe also, dass dies jemand anderem hilft, der auf denselben Fehler gestoßen ist, und ihm Zeit spart, diesen winzigen Fehler zu finden.]

winklerrr
quelle
0

Dies kann passieren, wenn ein Komma fehlt. Ich bin darauf gestoßen, als ich eine Liste mit zwei Tupeln hatte, von denen jedes aus einer Zeichenfolge an der ersten Position und einer Liste an der zweiten bestand. In einem Fall habe ich fälschlicherweise das Komma nach der ersten Komponente eines Tupels weggelassen, und der Interpreter dachte, ich würde versuchen, die erste Komponente zu indizieren.

Dumbledad
quelle
0

Ich hatte ein ähnliches Problem mit Pandas. Sie müssen die Funktion iterrows () verwenden, um eine Pandas-Dataset- Pandas-Dokumentation für Iterrows zu durchlaufen

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

Beachten Sie, dass Sie den Index im Dataset verarbeiten müssen, der auch von der Funktion zurückgegeben wird.

coremonkey
quelle