IndexError: list index out of range

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
kurvenschubser
User
Beiträge: 15
Registriert: Montag 10. März 2008, 01:49
Wohnort: Berlin

Hallo zusammen,
nach langem Aufschieben möchte ich mich mal ein wenig mit Programmieren beschäftigen. Ich habe mir dazu das http://www.galileocomputing.de/openbook/python/ Buch mal angeschaut, bekomme aber bei meinem kleinen Algorithmus dieses Problem:

Traceback (most recent call last):
File "/home/malte/software-schmiede/klauswert/src/klauswert.py", line 14, in <module>
notenkuerzeldict[zuordnung[0]] = zuordnung[1]
IndexError: list index out of range

Code: Alles auswählen

notenkuerzeldict = {}                       #Zum Referenzieren der Noten
dateiObj2 = open( "notenbezeichnungen.txt", "r" )
for line in dateiObj2:
    line = line.strip()
    zuordnung = line.split("    ")
    notenkuerzeldict[zuordnung[0]] = zuordnung[1]
dateiObj2.close()
Die dazugehörige Datei notenbezeichnungen.txt hat keine letzte freie Zeile:

Code: Alles auswählen

1	1,0
2	1,3
3	1,7
4	2,0	
5	2,3
6	2,7
7	3,0
8	3,3
9	3,7
10	4,0
11	5,0

Zuvor hab ich die Datei notenbezeichnungen schon einmal verwendet, so dass der Code so aussieht:

Code: Alles auswählen

dateiObj1 = open( "notenbezeichnungen.txt", "r" )  #Zur Ausgabe als Liste
notenkuerzel = dateiObj1.read()
dateiObj1.close()

notenkuerzeldict = {}                                     #Zum Referenzieren der Noten
dateiObj2 = open( "notenbezeichnungen.txt", "r" )
for line in dateiObj2:
    line = line.strip()
    zuordnung = line.split("    ")
    notenkuerzeldict[zuordnung[0]] = zuordnung[1]
dateiObj2.close()
Was ist das Problem? Bin dankbar für jeden Hinweis, hab auch schon recht viele Internetecken abgegrast auf der Suche nach Lösungen.
MfG
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Da funktioniert eben das `split`nicht. Ein `split`an " " ist auch...ungaublich blöd.

Und das Buch ist auch doof, arbeite lieber das offizielle Tutorial auf python.org durch.

Tip zum debuggen:

Code: Alles auswählen

notenkuerzeldict = {}                       #Zum Referenzieren der Noten
dateiObj2 = open( "notenbezeichnungen.txt", "r" )
for line in dateiObj2:
    line = line.strip()
    zuordnung = line.split("    ")
    try:
        notenkuerzeldict[zuordnung[0]] = zuordnung[1]
    except IndexError:
        import pdb; pdb.set_trace
dateiObj2.close()
Dann wird der debugger gestartet, wenn der Index Error auftritt und du kannst dir das in Ruhe anschaun.

Btw:
http://www.python.org/dev/peps/pep-0008/
Dringend anschaun :D
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Moin,
kurvenschubser hat geschrieben:Was ist das Problem? Bin dankbar für jeden Hinweis, hab auch schon recht viele Internetecken abgegrast auf der Suche nach Lösungen.
du verlässt dich darauf, dass deine Daten mit vier Leerzeichen getrennt sind, was sie wohl nicht immer sind (im Gegensatz zu deinem Beispiel). Wenn in einer Zeile deine Daten mal mit weniger als vier Leerzeichen getrennt sind, dann trennt split nichts, sondern gibt dir eine Liste mit nur einem Eintrag zurück: die ganze Zeile. In deinem Code versuchst du auf den zweiten Eintrag in der Liste zuzugreifen (zuordnung[1]), den es hier aber nicht gibt. Deswegen der Index-Fehler.

Du könntest den Code robuster machen, indem du die Trennung mit einer Regex machst. Schau mal ins re-Modul.

Gruß,
Manuel
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo kurvenschubser!

Willkommen im Python-Forum!

Du hast in deinem Textbeispiel in der vierten Zeile am Ende Leerzeichen dran hängen. Das merkt man, wenn man hier im Forum den Text mit der Maus markiert. audax hat es schon gezeigt: Falls sichergestellt ist, dass die Einträge IMMER mit vier Leerzeichen getrennt sind, dann genügt es, wenn du die unsichtbaren Zeichen vor und nach dem Text mit ``strip()`` löscht.

Code: Alles auswählen

for line in textfile:
    line = line.strip()
    if line:
        kuerzel, note = line.split()
        ...
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
kurvenschubser
User
Beiträge: 15
Registriert: Montag 10. März 2008, 01:49
Wohnort: Berlin

Danke für die Hinweise, ich hab die Liste auf Abstände mit 4 Leerzeichen getrimmt. Vorher wollte ich eigtl. den TAB als Separator, mit 4 Leerzeichen ist es aber ja sicherer. REs sind mir im Moment ein wenig kompliziert. Ich muss erstmal dei Basics hin bekommen...

MfG
BlackJack

Nimm doch einfach nur ``line.split()`` ohne Argument. Das trennt an "whitespace" allgemein, also egal ob nun ein Leerzeichen, hunderte oder auch Tabs.
kurvenschubser
User
Beiträge: 15
Registriert: Montag 10. März 2008, 01:49
Wohnort: Berlin

Der Teil des Programms sieht nun so aus:

Code: Alles auswählen

notenkuerzeldict = {}                                     #Zum Referenzieren der Noten
dateiObj2 = open("notenbezeichnungen.txt", "r")
for line in dateiObj2:
    line = line.strip()
    zuordnung = line.split()
    notenkuerzeldict[zuordnung[0]] = zuordnung[1]
dateiObj2.close()
Mittlerweile macht das Ganze schon ein wenig mehr her, werde dann evtl. mal das Resultat im Forum posten :D

Danke für die Tips!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich würde folgendes machen, statt:

Code: Alles auswählen

zuordnung = line.split()
lieber das und dann bist du die Indizes los.

Code: Alles auswählen

name, kuerzel = line.split()
(die Namen darfst du dir natürlich aussuchen)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
kurvenschubser
User
Beiträge: 15
Registriert: Montag 10. März 2008, 01:49
Wohnort: Berlin

Ja das sieht ja auch ein wenig leserlicher aus
BlackJack

Ist irgendwie noch ein bisschen lang. Ungetestet:

Code: Alles auswählen

    datei = open('notenbezeichnungen.txt')
    notenkuerzel = dict(zeile.split() for zeile in datei)
    datei.close()
kurvenschubser
User
Beiträge: 15
Registriert: Montag 10. März 2008, 01:49
Wohnort: Berlin

BlackJack hat geschrieben:Ist irgendwie noch ein bisschen lang. Ungetestet:

Code: Alles auswählen

    datei = open('notenbezeichnungen.txt')
    notenkuerzel = dict(zeile.split() for zeile in datei)
    datei.close()
Das klappt. Ist es performancetechnische besser solchen kurzen Code zu schreiben oder sollte man eher ausführlicher schreiben?

MfG
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

kurvenschubser hat geschrieben: Das klappt. Ist es performancetechnische besser solchen kurzen Code zu schreiben oder sollte man eher ausführlicher schreiben?
Naja, generell sollte es übersichtlich sein - und daraus resultiert ja i.A., dass man es kürzer schreibt.
Ausnahmen stellen dann eher Daten dar, die oft gebraucht werden und bei denen es aufwendig ist, diese dauernd neu zu berechnen. Da würde ich diese immer in eine Variable speichern und die Berechnung nur dann durchführen, wenn sich etwas ändert / ändern könnte.
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Meiner Erfahrung ist der direkteste Code auch der schnellste. Bei dem Beispiel sollte es aber kaum einen Unterschied geben...

Eingebaute Loops (List Comprehensions, map, filter) sind generell fixer aber als explizite Schleifen und auch meist leichter verständlich.
Antworten