Einlesen von regelmäßig ungleichen zeilen

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.
quant
User
Beiträge: 34
Registriert: Freitag 29. Mai 2009, 12:06

huhu

also ich hab mal versucht den code zu verstehen was mir auch glaub ich gelungen ist ... nun hab ich einige probleme wo ich vlt hilfe brauch

er macht immer ärger wenn ich den flag setzen will für incoming und outgoing in zeile 28... da versteh ich das problem nicht

ab zeile 30 muss ich neu sortieren damit nur die zeilen welche nicht header und nicht event und natürlich auch nur incoming sind erfasse, irgendwie fällt mir da aber nix ein ich hab schon viel rumprobiert aber entweder läuft es garnicht oder er erfasst immer alle zeilen

Code: Alles auswählen

# /usr/bin/python
# coding:utf-8

import pprint
DATAFILE = "fort.15"
# 'enum' is sometimes dearly missed
SCAN, ENTRY_HEAD, ENTRY_IN, ENTRY_OUT = range(4)
def main():
    #to hold all extracted data,
    events = []
    state = SCAN
    with open(DATAFILE) as data_fd:
        for line in data_fd:
            if state == SCAN and line[0] == "0":
                    incoming = outgoing = 0
                    state = ENTRY_HEAD
            elif state == ENTRY_HEAD or \
                    (state == SCAN and line[0] in "123456789"):
                #prepare counter
                if line[0] in "123456789" and not line[2:9] in "0":
                    incoming,outgoing = int(line[0:1]), int(line[2:9])
                    #create new entry
                    events.append( dict(incoming=[], outgoing=[]) )
                    #local shortcuts (I'm a lazy typist) 
                    in_tmp = events[-1]["incoming"]
                    out_tmp = events[-1]["outgoing"]
                    # select next state
#                    state = ENTRY_IN if incoming else ENTRY_OUT
                    state = ENTRY_IN 
            elif state == ENTRY_IN:
                #pass
                 if line[6:22]:
                     print line[6:22]
#		 print type(int(line[156:160]))
#                in_tmp.append(int(line[156:160]))
#                incoming -= 1
#                if not incoming:
#                    state = ENTRY_OUT
#            elif state == ENTRY_OUT:
#                out_tmp.append(int(line[149:161]))
#                outgoing -= 1
#                if not outgoing:
#                    state = SCAN
            else:
#                # print "impossible state:", state
                raise IOError("file wrongly formatted")
    for data in events:
        pprint.pprint(data)
                
if "__main__" == __name__ : main()
BlackJack

@b.esser-wisser: Für Enums verwende ich meistens das hier: http://pypi.python.org/pypi/enum/

Andererseits kann man Zustandsautomaten in Python auch ganz nett mit Funktion/Methoden oder Klassen bauen. Dann hat man nicht alles in einem riesigen "switch" und keine Indirektion über "magische Zahlen" oder Enum-Objekte.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

@BlackJack:
Meinst du das ungefähr so?

Code: Alles auswählen

class FileParser(object):
    def __init__(self, **kwargs):
        # ...
        self.next_step = self.seek_header
    def seek_header(self, line):
        # ...
        self.next_step = read_in_events
    def read_in_events(self, line):
        # ...
        self.next_step = read_out_events
    def read_out_events(self, line):
        # ...
        self.next_step = self.seek_header
    def parse_file(self):
        for line in self.file:
            self.next_step(line)
Bei "for line in file()" funktioniert ja file.tell()nicht richtig/nicht wie erwartet, wenn man sich also lieber raussschreibt, an welchen Stellen was interessantes steht, muss man die Schleife ändern :( -- das Dateiformat ist da auch blöde: Einträge mit fester Länge und unterschiedlich lange Zeilen, so dass man nicht aus der Zeilennummer den offset ausrechnen kann.

hth, Jörg
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
quant
User
Beiträge: 34
Registriert: Freitag 29. Mai 2009, 12:06

hmmm also ich hab heute nochmal versucht die oben beschriebenen probleme zu lösen , aber irgendwie komm ich da nicht weiter, wenn ihr mir helfen könnt wäre echt super

lg
BlackJack

@b.esser-wisser: Jup, das Muster meinte ich.
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

@quant: Kannst du mal präzise deine Probleme beschreiben - mit "Der macht ärger", "geht nicht" etc. kann niemand was anfangen.

Hast du noch Probleme mit dem Ablauf?
1. finde eine Zeile die mit "0" fängt (nicht mit 0 oder " 0" oder "\t0")
2. in der nächsten Zeile kommt jetzt:
- die Anzahl an 'incoming'-Zeilen im Zeichen 0, d.h. im ersten Zeichen
- die Anzahl an 'outgouing'-Zeilen, Zeichen 1 bis 8 (woher weiß ich das?)
3. die nächsten Zeilen (wieviele?) sind incoming-Zeilen, die Zahl, die du hier suchst steht an Zeichen 149 bis 159, bzw. in Python "aktuelle_zeile[149:160]"
4. die nächsten Zeilen sind 'outgoing'-Zeilen -- Die können auch fehlen
weiter zu 1.

Arbeite auf jeden Fall das Tutorial durch - offiziell in englisch in der/deiner Python-Documentation, oder (IIRC im Python-Wiki) auf Deutsch.

hth. Jörg
Wir haben schon 10% vom 21. Jahrhundert hinter uns!
quant
User
Beiträge: 34
Registriert: Freitag 29. Mai 2009, 12:06

hey

also ich hab folgendes problem ... in der ENTRY_OUT schleife ist die outgoing variable aus mir unverständlichen gründen 0, obwohl sie vorher noch die richtige zahl hat, welche ich vorher ja einlese

Code: Alles auswählen


# /usr/bin/python
# coding:utf-8

import pprint
DATAFILE = "fort.15"
# 'enum' is sometimes dearly missed
SCAN, ENTRY_HEAD, ENTRY_IN, ENTRY_OUT = range(4)
def main():
    #to hold all extracted data,
    events = []
    state = SCAN
    with open(DATAFILE) as data_fd:
        for line in data_fd:
            if state == SCAN and line[0] == "0":
                    incoming = outgoing = 0
                    state = ENTRY_HEAD
            elif state == ENTRY_HEAD or \
                    (state == SCAN and line[0] in "123456789"):
                #prepare counter
                if line[0] in "123456789" and not line[2:9] in "0":
                    incoming,outgoing = int(line[0:1]), int(line[2:9])
                    #create new entry
                    events.append( dict(incoming=[], outgoing=[]) )
                    #local shortcuts (I'm a lazy typist)
                    in_tmp = events[-1]["incoming"]
                    out_tmp = events[-1]["outgoing"]
                    # select next state
                    state = ENTRY_IN if incoming else ENTRY_OUT
            elif state == ENTRY_IN:
#                in_tmp.append(int(line[156:160]))
                incoming -= 1
#             print outgoing
                if not incoming:
                    state = ENTRY_OUT
            elif state == ENTRY_OUT:
#                out_tmp.append(int(line[149:161]))
                print outgoing # hier ist sie 0...
                outgoing -= 1
                if not outgoing:
                    state = SCAN
            else:
#                # print "impossible state:", state
                raise IOError("file wrongly formatted")
    for data in events:
        pprint.pprint(data)
               
if "__main__" == __name__ : main()
ansonsten ist mir die logic schon klar vom ganzen
Benutzeravatar
b.esser-wisser
User
Beiträge: 272
Registriert: Freitag 20. Februar 2009, 14:21
Wohnort: Bundeshauptstadt B.

line[2:9] in "0"
funktioniert definitiv nicht - probier's im interpreter aus
int(line[2:9]) == 0
geht wahrscheinlich besser.
Aber: Gib doch besser das Ergebnis nach den Incoming-Zeilen aus, wenn outgoing==0 ist, und überspring "ENTRY_OUT" einfach.
Antworten