strukturierte Datei einlesen

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
pythoniser
User
Beiträge: 9
Registriert: Donnerstag 7. Dezember 2006, 18:04

Hallo zusammen,

Ich möchte eine Datei einlesen (als Liste oder Array), welche folgendermassen strukturiert ist:

Code: Alles auswählen

Preiselbeeren, Brombeeren, ....
Seerosen...
         (Leere Zeile)
    BaumNr.     AnzBlätter      Ort          Höhe[m]       Breite[m] Umfang[m]
         1               200       BB              .5                 0.8              2
         2                50       Rtburg          .4                   1            1.5
		  usw.
--> beachtet die Leerzeichen jeweils am Anfang der Blöcke, z.B. BaumNr.

Ziel ist, diese Angaben in eine andere Datei auszulesen (anders strukturiert und man muss mit den obigen Werte rechnen können, müssen also vom Typ float sein und einzeln ansprechbar sein, wie z.B. Liste[0])
Normalerweise (d.h. wenn es nicht unterschiedlich viele Leerzeichen gibt) würde ich es so machen:

Code: Alles auswählen

for line in file:
for line in zeile:
	if line.startswith("P"):    #um die 1. Kommentarzeile zu überspringen
		continue
		if line.startswith("S"):     #um die 2. Kommentarzeile zu überspringen
			continue
			if line.startswith("              "):   #um die Leere Zeile zu überspringen
				continue
			else:
			a, b, c, d, e, f=line.split("  ")
			print a, b, c, d, e, f

	

Jedoch bringt dies folgenden Error: Name 'b' not defined.
Ich denke, dies ist wegen den ungleich vielen Leerzeichen, welche die verschiedenen Blöcke wie BaumNr., usw.. trennen und dem line.split(" "), welcher die strings nach jedem leerzeichen trennt...

Diese Leerschläge will ich jedoch nicht manuell verändern,
da ich sehr viele solche Dateien habe (es ist einfach zu zeitaufwändig). Besser wäre es diese irgendwie rauszuschmeissen. Wie?

Wäre eine andere Einlesemethode besser? Welche?

Zusätzlich frage ich mich, wie ich die Zahlen in Fliesskommazahlen umwandeln kann. Ich möchte etwas wie dies machen:
map(string.atof, Liste). Jedoch habe ich im obigen Code keine sichtbare Liste. -->?

Und, würdet ihr den Header mit den Infos Preiselbeeren, usw... anders überspringen? Wie?

Vielen Dank für jeglichen Input!
BlackJack

Die Meldung kann aber nicht von dem gezeigten Quelltext kommen. Mal abgesehen davon, das die Einrückung fehlerhaft ist, wäre `a` auch nicht definiert, wenn `b` nicht definiert ist. Oder es gibt ein `a` das vorher schon an etwas gebunden wurde.

Den Block am Anfang würde ich überspringen, indem ich solange Zeilen überlese bis ich bei der Kopfzeile der Tabelle angekommen bin. Und die Daten könnte man so umwandeln:

Code: Alles auswählen

source = """
Preiselbeeren, Brombeeren, ....
Seerosen. 
         (Leere Zeile)
    BaumNr.     AnzBlätter      Ort          Höhe[m]       Breite[m] Umfang[m] 
         1               200       BB              .5                 0.8              2
         2                50       Rtburg          .4                   1            1.5
""".splitlines(True)


def main():
    lines = iter(source)
    # 
    # Skip to header.
    # 
    for line in lines:
        if line.strip().startswith('BaumNr'):
            break
    
    for line in lines:
        print [convert(item)
               for convert, item
               in zip((int, int, str, float, float), line.split())]
pythoniser
User
Beiträge: 9
Registriert: Donnerstag 7. Dezember 2006, 18:04

Danke für den Input. Es ist so, dass dies ein fiktives Bsp. ist, deswegen stimmen die Einrückungen, usw. wohl nicht ganz. Und die Datei ist nicht so klein, dass ich sie einfach so in die Variable "source" reinschreiben könnte. Sie hat ziemlich viele Zeilen und seeehr viele Blöcke (d.h. noch mehr Spalten mit z.B. Aufnahmedatum, Beobachter, usw...). Ich hätte die Datei mittels datei=open("C:\Bäume.txt", "r") geöffnet, und nicht alles in den Programmcode (d.h. in die Variable source) schreiben wollen...
BlackJack

Das war ja auch nur ein kleines Beispiel und funktioniert auch mit einer Datei anstelle der Liste mit den Zeilen. Ein Datei-Objekt ist in Python auch "iterable" und liefert die einzelnen Zeilen.
pythoniser
User
Beiträge: 9
Registriert: Donnerstag 7. Dezember 2006, 18:04

oh, ok. Wusste ich nicht. Bin noch am Anfang meiner Python-Karriere (':wink:')
Könntest du mir dazu einen kleinen Tipp geben?

Soll ich die Baum-Datei als Liste einlesen?
BlackJack

Du kannst eine Datei als "iterable" behandeln, also einfach als Iterator über die Zeilen verwenden. Wenn der Inhalt von `source` in einer Datei steht, dann sähe das Testprogramm fast gleich aus:

Code: Alles auswählen

def main():
    lines = open('test.txt', 'r')
    # 
    # Skip to header.
    # 
    for line in lines:
        if line.strip().startswith('BaumNr'):
            break
    
    for line in lines:
        print [convert(item)
               for convert, item
               in zip((int, int, str, float, float), line.split())]
    
    lines.close()
An der grundlegenden Verarbeitung ändert sich nichts wenn man statt über eine Liste mit Zeilen, über eine Datei mit Zeilen iteriert.
pythoniser
User
Beiträge: 9
Registriert: Donnerstag 7. Dezember 2006, 18:04

Danke vielmals! :D Ich werds ausprobieren und meld mich morgen, falls was nicht funktioniert.

Noch eine Frage: Wie kann ich die Werte ansprechen (à la liste[0][1])? z.B. möchte ich die Höhe 0.4 (in der zweiten Reihe) ansprechen, um damit zu rechnen (und dies in eine Datei ausgeben). Mit item?
pythoniser
User
Beiträge: 9
Registriert: Donnerstag 7. Dezember 2006, 18:04

Code läuft. Das Problem ist folgendes: möchte ich z.B:

Code: Alles auswählen

 print lines[4][5]
oder auch nur print lines [7], kommt: NameError: name 'lines' is not defined. lines wurde doch in main() definiert -->?!?[/quote]
BlackJack

Ja es wurde in der *main* definiert. Wo steht Dein ``print``?

Allerdings ist `lines` zumindest im letzten Beispiel keine Liste sondern das Datei-Objekt und darauf kann man nicht so zugreifen. Arbeite am besten mal das Python-Tutorial durch um ein Gefühl für die Sprache zu bekommen.
pythoniser
User
Beiträge: 9
Registriert: Donnerstag 7. Dezember 2006, 18:04

Ich hab mein 'print' einmal ausserhalb der main() und einmal innerhalb gehabt. Ausserhalb führt es zu einem Error, innerhalb führt es zu gar nichts (keine Reaktion). Auch wenn ich innerhalb von main() z.B. ein print '*******' ausgeben möchte, passiert nichts.

Zusätzlich ist mir nicht klar, wie ich auf die Werte zugreifen kann. Das Ziel ist, dass ich etwas mit dem Umfang der Bäume machen kann. Könntest du mir bitte ein Tipp geben? Danke!
BlackJack

Ich tippe mal darauf, dass Du die `main()` nicht aufrufst. Es wird nur das ausgeführt, was auf Modulebene steht.

Code: Alles auswählen

def convert_line(line):
    return [convert(item)
            for convert, item
            in zip((int, int, str, float, float, float), line.split())]


def read_table(lines):
    lines = iter(lines)
    # 
    # Skip to header.
    # 
    for line in lines:
        if line.strip().startswith('BaumNr'):
            break
    
    return map(convert_line, lines)


def main():
    lines = open('test.txt', 'r')
    table = read_table(lines)
    lines.close()

    print table[1][5]   # Zeile 1 (= Baum Nr. 2), Umfang (letzte Spalte)


if __name__ == '__main__':
    main()
Antworten