Bestimmung der numberline innerhalb einer zip

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
aqualx
User
Beiträge: 7
Registriert: Donnerstag 9. April 2020, 19:54

Hallo zusammen,

ich suche nach einer Möglichkeit die numberline einer spezifischen Zeichenfolge innerhalb einer archivierten dat-Datei zu bestimmen.

Code: Alles auswählen

from zipfile import ZipFile

with ZipFile('archived_file.zip') as archive:
    f = archive.open('folder/file.dat')
    lines = f.readlines()[34:]  # reading at the 34th line
Diese Zeichenfolge ist ein '***', die in der Testdatei in der 34. Zeile auftaucht. Nach der Zeichenfolge folgt eine Tabelle, die ich gerne in eine liste (später in ein dataframe) speichern würde.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Du brauchst dafür keine Zeilennummer.
Du iterierst über die Zeilen und schaust, ob du in der Zeile findest, was du suchst.
Dann iterierst du weiter und verarbeitest die kommenden Zeilen, bis etwas vorbei kommt, das das Ende der Tabelle kennzeichnet.
aqualx
User
Beiträge: 7
Registriert: Donnerstag 9. April 2020, 19:54

ich habs jetzt mit einer while-Schleife versucht in der ich alle Zeilen des Dokuments durchgehe und je das erste Zeichen teste.

Code: Alles auswählen

from zipfile import ZipFile

with ZipFile('testdatei.zip') as archive:
    f = archive.open('Ordner/Datei.dat')
    
i = 0
stop = False

while (not stop):
    line = f.readline()
    i += 1 
    if (line[0] == '*'): stop = True
die Laufvariable i sollte demnach den Wert 34 bekommen. Leider ist dem nicht so. Wo liegt der Fehler?

Und wie kann ich nicht nur nach '*' suchen, sondern nach '***'?
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@aqualx: Die Klammern um die Bedingungen gehören da nicht hin und man schreibt der lesbarkeit halber auch einzelne Zeilen in einem Block in eine eigene Zeile. `readline()` ist ineffizient, man iteriert direkt über die Zeilen des Dateiobjekts. Das man bitte nicht `f` nennt sondern `file` oder `lines`. Wenn man zusätzlich zu den Elementen eines iterierbaren Objekts noch eine laufende Zahl braucht, dann gibt es dafür die `enumerate()`-Funktion. Aber wozu brauchst Du überhaupt die Zahl?

Das `stop`-Flag ist überflüssig wenn man eine Endlosschleife schreibt, die an der entsprechenden Stelle mit `break` verlassen wird.

``line[0]`` kann einem auf die Füsse fallen wenn `line` eine leere Zeichenkette ist. Kann hier nicht passieren, aber mit das Problem kann man mit der `startswith()`-Methode umgehen. Was dann auch die Frage nach der Suche nach "***" beantworten sollte.

Was bekommst Du denn statt 34 für einen `i`-Wert? Und hast Du Dir `i` und ``line[0]`` denn einfach mal *in* der Schleife ausgeben lassen‽ Was erwartest Du da und in wie weit weichen die Ausgaben von Deinen Erwartungen ab?

Edit: Achtung, fehlerhaft:

Code: Alles auswählen

from zipfile import ZipFile


def main():
    with ZipFile("testdatei.zip") as archive:
        with archive.open("folder/file.dat") as lines:
            i = None
            for i, line in enumerate(lines):
                if line.startswith("*"):
                    break
            print(i)


if __name__ == "__main__":
    main()
Hier wird dann eine Ausnahme ausgelöst die den Fehler in Deinem Programm zeigt. Basically:

Code: Alles auswählen

In [99]: "*" == b"*"                                                            
Out[99]: False
Also entweder auf `bytes`-Ebene arbeiten, oder das `io`-Modul zur Hilfe nehmen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten