Ik speel met zowel het leren van python als het proberen om github-problemen in een leesbare vorm te krijgen. Met behulp van het advies op Hoe kan ik JSON naar CSV converteren? kwam ik met dit:
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"]])
Waarbij “issues.json” het json-bestand is dat mijn github-problemen bevat. Als ik dat probeer uit te voeren, krijg ik
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
Wat mis ik hier? Wat zijn de “stringindexen”? Ik weet zeker dat als ik dit eenmaal werkend heb, ik meer problemen zal hebben, maar voor nu zou ik graag willen dat dit werkt!
Als ik de for
-instructie aanpas om eenvoudig
for item in data:
print item
wat ik krijg is … “problemen” — dus ik doe iets fundamentelers verkeerd. Hier is een beetje van mijn 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...
wanneer ik data
afdruk, lijkt het alsof het heel vreemd wordt vermengd:
{u'issues': [{u'body': u'Add missing paging (Older>>) lin...
Antwoord 1, autoriteit 100%
item
is hoogstwaarschijnlijk een tekenreeks in uw code; de tekenreeksindexen zijn die tussen vierkante haken, bijvoorbeeld gravatar_id
. Dus ik zou eerst je variabele data
controleren om te zien wat je daar hebt ontvangen; Ik denk dat data
een lijst met strings is (of op zijn minst een lijst met minstens één string), terwijl het een lijst met woordenboeken zou moeten zijn.
Antwoord 2, autoriteit 126%
De variabele item
is een string. Een index ziet er als volgt uit:
>>> mystring = 'helloworld'
>>> print mystring[0]
'h'
In het bovenstaande voorbeeld wordt de index 0
van de tekenreeks gebruikt om naar het eerste teken te verwijzen.
Tekenreeksen kunnen geen tekenreeksindexen hebben (zoals woordenboeken dat wel kunnen). Dit werkt dus niet:
>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
Antwoord 3, autoriteit 40%
TypeError voor segmentnotatie str[a:b]
Kort antwoord
Gebruik een dubbele punt :
in plaats van een komma tussen de twee indices a
en b
in str[a:b]
(bijv. in plaats van my_string[0,5]
schrijf my_string[0:5]
) .
Lang antwoord
Bij het werken met strings en slice-notatie (een common sequence-bewerking), kan het gebeuren dat een TypeError
wordt gegenereerd, wat erop wijst dat de indices gehele getallen moeten zijn, zelfs als ze dat duidelijk zijn .
Voorbeeld
>>> my_string = "hello world"
>>> my_string[0,5]
TypeError: string indices must be integers
We hebben duidelijk twee gehele getallen voor de indices doorgegeven aan de slice-notatie, toch? Dus wat is hier het probleem?
Deze fout kan erg frustrerend zijn – vooral aan het begin van het leren van Python – omdat de foutmelding een beetje misleidend is.
Uitleg
We hebben impliciet een tupel van twee gehele getallen (0 en 5) doorgegeven aan de plaknotatie toen we my_string[0,5]
aanriepen omdat 0,5
(zelfs zonder de haakjes) evalueert tot hetzelfde tuple als (0,5)
zou doen.
Een komma ,
is eigenlijk genoeg voor Python om iets als een tuple te evalueren:
>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>
Dus wat we daar deden, deze keer expliciet:
>>> my_string = "hello world"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers
Nu is de foutmelding tenminste logisch.
Oplossing
We moeten de komma ,
vervangen door een dubbele punt :
om de twee gehele getallen correct te scheiden:
>>> my_string = "hello world"
>>> my_string[0:5]
'hello'
Een duidelijkere en nuttigere foutmelding had zoiets kunnen zijn als:
TypeError: string indices must be integers (not tuple)
Een goede foutmelding laat de gebruiker direct zien wat hij verkeerd heeft gedaan en het zou duidelijker zijn geweest hoe het probleem kon worden opgelost.
[Dus de volgende keer dat u merkt dat u verantwoordelijk bent voor het schrijven van een foutbeschrijvingsbericht, denk dan aan dit voorbeeld en voeg de reden of andere nuttige informatie toe aan het foutbericht zodat u en misschien andere mensen begrijpen wat er fout is gegaan.]
Leren geleerd
- slice-notatie gebruikt dubbele punten
:
om de indices (en stapbereik, bijv.str[from:to:step]
) te scheiden - tupels worden gedefinieerd door komma’s
,
(bijv.t = 1,
) - wat informatie aan foutmeldingen toevoegen zodat gebruikers begrijpen wat er mis is gegaan
Proficiat en veel plezier met programmeren
winklerrr
[Ik weet dat deze vraag al is beantwoord en dit was niet precies de vraag die de topicstarter stelde, maar ik kwam hier vanwege het bovenstaande probleem dat tot dezelfde foutmelding leidt. Het kostte me in ieder geval behoorlijk wat tijd om die kleine typfout te vinden.
Dus ik hoop dat dit iemand anders zal helpen die op dezelfde fout is gestuit en dat het hem wat tijd bespaart om die kleine fout te vinden.]
Antwoord 4, autoriteit 37%
data
is een dict
object. Herhaal het dus als volgt:
Python 2
for key, value in data.iteritems():
print key, value
Python 3
for key, value in data.items():
print(key, value)
Antwoord 5, autoriteit 2%
Ik had een soortgelijk probleem met Panda’s, je moet de functie iterrows() gebruiken om een Pandas-dataset te doorlopen Pandas-documentatie voor iterrows
data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
print('{} {}'.format(item["gravatar_id"], item["position"]))
merk op dat u de index in de dataset moet behandelen die ook door de functie wordt geretourneerd.
Antwoord 6
Dit kan gebeuren als er een komma ontbreekt. Ik kwam het tegen toen ik een lijst met twee-tupels had, die elk bestonden uit een string op de eerste positie en een lijst op de tweede. In één geval heb ik ten onrechte de komma na de eerste component van een tupel weggelaten, en de interpreter dacht dat ik de eerste component probeerde te indexeren.
Antwoord 7
Als vuistregel, wanneer ik deze fout ontvang in Python, vergelijk ik de functiehandtekening met de functie-uitvoering.
Bijvoorbeeld:
def print_files(file_list, parent_id):
for file in file_list:
print(title: %s, id: %s' % (file['title'], file['id']
Dus als ik deze functie aanroep met parameters in de verkeerde volgorde geplaatst en de lijst doorgeef als het 2e argument en een string als het 1e argument:
print_files(parent_id, list_of_files) # <----- Accidentally switching arguments location
De functie zal proberen de parent_id
string te herhalen in plaats van file_list
en zal de index verwachten als een geheel getal dat verwijst naar het specifieke teken in de string en niet een index die een tekenreeks is (title
of id
).
Dit leidt tot de fout TypeError: string indices must be integers
.
Vanwege zijn dynamische aard (in tegenstelling tot talen als Java, C# of Typescript), zal Python u niet informeren over deze syntaxisfout.