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
Bullet
User
Beiträge: 2
Registriert: Montag 19. März 2012, 22:19

Montag 19. März 2012, 22:47

Hallo,

ich studiere Physik und versuche zur Zeit eine relativ große Menge an Messdaten zu formatieren.
Hier zunächst erstmal mein Skript:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Datei zeilenweise parsen
daten_in = open("x02", "r")
daten_out = open("part_2.mol2", "w")

i = 0
for zeile in daten_in:
    liste = zeile.split()
    i=i+1
    liste0, liste1, liste2, liste3 = liste[0], float(liste[1]), float(liste[2]), float(liste[3])
    daten_out.write('{0:1d} {1:2s}{2:2.2f} {3:2.2f} {4:2.2f} {5:2s}\n' .format(i, liste0, liste1, liste2, liste3, liste0))

daten_out.close()
daten_in.close()
Die eingelesene Datei x02 besteht aus 4 Spalten mit jeweils 767 Zeilen.
Beim Ausführen des Skripts erhalte ich jedoch stets die Fehlermeldung: list index out of range und in der Ausgabe-datei wird schon weit vor Eintrag 767 abgebrochen.

Ist die Datenmenge evtl. zu groß? (wohl eher nicht)
Weiß jemand, wie man das Problem lösen kann, so dass alle Messdaten erfasst werden?

Vielen Dank im Voraus,


Bullet
Zuletzt geändert von Anonymous am Montag 19. März 2012, 23:24, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Benutzeravatar
snafu
User
Beiträge: 5835
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Montag 19. März 2012, 23:02

Bullet hat geschrieben:Beim Ausführen des Skripts erhalte ich jedoch stets die Fehlermeldung: list index out of range und in der Ausgabe-datei wird schon weit vor Eintrag 767 abgebrochen.
Deutet stark darauf hin, dass an irgendeiner Stelle weniger Elemente (resp. Whitespace als Trenner) vorhanden ist, als du erwartest.

Du nimmst ja schon die Zeilennummern mit. Guck also mal, bis wohin er kommt und wirf dann einen Blick auf die drauf folgende Zeile. Dort kann eigentlich nur der Fehler liegen.
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Montag 19. März 2012, 23:05

Hallo und willkommen im Forum!

Die Fehlermeldung sagt dir, dass in einer Liste kein Element mit dem gegebenen Index existiert. Wahrscheinlich liegt es einfach daran, dass eine der Zeilen in der Datei leer ist. Lass dir die Zeilen doch einfach mal mittels print in der Schleife ausgeben, dann siehst du das Problem. Außerdem können noch einige Dinge an deinem Code verbessert werden:

- Dateien solltest du mit dem with-Statement öffnen, dann werden diese automatisch, auch im Fehlerfall, wieder geschlossen.
- Wenn du einen Index innerhalb einer Schleife brauchst, dann solltest du enumerate verwenden:

Code: Alles auswählen

for index, zeile in enumerate(daten_in)
- liste0, liste1, liste2, liste3 sind sehr nichtssagende Bezeichner, du solltest dir bessere/sprechendere Namen einfallen lassen.
- Schau dir mal das csv-Modul an, das macht einen großteil deines Codes überflüssig
- Da du mit den Daten vielleicht arbeiten möchtest, lohnt sich vielleicht auch ein Blick auf das numpy-Modul. Auch damit könntest du die Daten einlesen.

Sebastian

Edit: Und bitte zeige beim nächstem Mal bitte die genaue Fehlermeldung inklusive des gesamten Tracebacks. Du magst damit zwar (noch) nicht viel anfangen können, für die Helfenden ist es aber oft hilfreich.
Das Leben ist wie ein Tennisball.
BlackJack

Montag 19. März 2012, 23:30

@Bullet: Zusätzlich zu dem was meine Vorredner gesagt haben: Die erste Zahl in den Platzhaltern für die `format()`-Methode gibt an, das wievielte Argument an dieser Stelle formatiert werden soll. Damit kann man die Reihenfolge beeinflussen und auch Argumente mehrfach verwenden.
Bullet
User
Beiträge: 2
Registriert: Montag 19. März 2012, 22:19

Montag 19. März 2012, 23:31

Danke für die schnelle Antwort.
Ich habe mein Skript zunächst etwas bearbeitet:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Datei zeilenweise parsen
daten_in = open("x03", "r")
daten_out = open("part_3.mol2", "w")

for index, zeile in enumerate(daten_in):
    liste = zeile.split()
    part_typ, pos_x, pos_y, pos_z = liste[0], float(liste[1]), float(liste[2]), float(liste[3])
    print index+1, part_typ, pos_x, pos_y, pos_z, part_typ    
    daten_out.write('{0:1d} {1:2s}{2:2.2f} {3:2.2f} {4:2.2f} {1:2s}\n' .format(index+1, part_typ, pos_x, pos_y, pos_z, part_typ))

daten_out.close()
daten_in.close()
(die Sache mit dem with-statement habe ich auf die Schnelle nicht ganz verstanden und deshalb weggelassen)

Folgendes geschieht.

Tatsächlich liefert print die richtige Ausgabe aller 767 Einträge.
Die Ausgabedatei bricht jedoch bei Zeile 645 ab. Ich habe nachgeschaut, was in Zeile 645 ist. Doch mir ist nichts ungewöhnliches aufgefallen. Alles normal.
BlackJack

Montag 19. März 2012, 23:37

@Bullet: Das kann ja nicht sein, denn *vor* dem ``print`` ist die Zeile wo der Fehler auftauchen muss, also kann das ``print`` nicht problemlos für alle Zeilen durchlaufen.

Du übergibst `format()` jetzt übrigens noch ein Argument zu viel. ;-)
Benutzeravatar
snafu
User
Beiträge: 5835
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Montag 19. März 2012, 23:38

Das `csv`-Modul und Numpy sind schon sehr gute Stichworte. Falls es trotzdem "zu Fuß" sein soll, hätte ich hier einen robusteren Vorschlag (Python 2.7):

Code: Alles auswählen

from StringIO import StringIO

daten_in = StringIO("""\
foo 2345234 346546 575687 6789 45
bar 3453453 345656456 45756 457645

baz 234 34534534 3456 3456 335 645 54 4 234
""")

for index, zeile in enumerate(daten_in):
    werte = zeile.split()
    if werte:
        werte[1:] = map(float, werte[1:])
        zahlenteil = ' '.join(map('{:.2f}'.format, werte[1:]))
        print '{0} {1} {2} {1}'.format(index, werte[0], zahlenteil)
Die Namen sind natürlich bewusst abstrakt gehalten, weil ich den konkreten Anwendungsfall nicht kenne.

`StringIO()` ist hier selbstverständlich nur zu Demonstrationszwecken als Ersatz für dein Dateiobjekt gewählt worden.
Antworten