zipfile.read() und riesige Dateien

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
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

Hallöchen,

ich habe gerade erst begonnen mit Python (gestern), genauer gesagt versuch ich mich gerade an PyScripter 1.9.9.6 (PortablePython_1.1_py3.0.1.exe)

Ich habe mit in den letzten 2 Tagen ein Script geschrieben, welches in einem Ordner alle möglichen Unterordner nach *.zip-Dateien durchsucht, diese dann nach einer bestimmten Datei durchsucht, diese Datei einliest und innerhlab der Datei dann nach einen frei wählbaren String sucht. (der Hauptordner ist ca. 1,5TB groß und hat etwa 100.000 zip- und andere Dateien, die will ich ned per Hand durchsuchen :-) )

Mein Problem nun ist, dass in den zip-Dateien auch txt-Dateien enthalten sind, die entpackt > 50MB sind, die größte glaub auch mal so 250MB. Wenn ich diese einlesen will mittels zipfile.read() bekomme ich leider einen Memory-Error.

Jetzt habe ich hier im Forum schon diesen Thread gefunden: http://www.python-forum.de/viewtopic.ph ... ien#p44416

Aber ich komm damit ned klar ... wie gesagt, habe ich vorgestern mit Python angefangen ... jetzt mal so eben in den Modulen rumwurschteln ist dann doch noch eine andere Sache.

Kann mir das jemand so erklären, dass ich das auch verstehe, was ich ändern muss, damit ich auch diese riesigen Dateien einlesen kann? Wie gesagt ... geht einfach davon aus, dass ich ein relativer DAU in Sachen Python bin ... :-)
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

`zipfile.ZipFile.open` gibt einen File-like-Iterator (`zipfile.ZipExtFile`) zurück. Ungetestet:

Code: Alles auswählen

import zipfile
stream = zipfile.ZipFile('/foo/bar')
bla = stream.open('bla.txt')
for line in bla:
    print line
Das würde die Datei zeilenweise extrahieren. Alternativ kannst du auch eine bestimmte Menge an Bytes lesen:

Code: Alles auswählen

bla.read(8*1024)
liest immer 8KiB auf einmal (oder weniger, wenn die Datei kleiner ist, oder 0, wenn du am Ende der Datei angelangt bist).
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

Dauerbaustelle hat geschrieben:

Code: Alles auswählen

bla.read(8*1024)

liest immer 8KiB auf einmal (oder weniger, wenn die Datei kleiner ist, oder 0, wenn du am Ende der Datei angelangt bist).
Ääähhhmmm ... und wie bekomme ich den dann dazu, dass er die nächsten 8KB einliest? ... schreibe ich das bla.read(8*1024) noch mal hin, liest er doch wieder die gleicen Byte ein - oder?
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Graf_Dracula hat geschrieben:Ääähhhmmm ... und wie bekomme ich den dann dazu, dass er die nächsten 8KB einliest? ... schreibe ich das bla.read(8*1024) noch mal hin, liest er doch wieder die gleicen Byte ein - oder?
Nein.

Ansonsten schließe ich mich dem Beitrag von mkesper unter mir an.
Zuletzt geändert von /me am Freitag 18. Februar 2011, 09:15, insgesamt 1-mal geändert.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Ich würde eher zeilenweise arbeiten. Ansonsten kann der Suchstring ja genau zwischen zwei Blöcken liegen. Und Daten 8k-weise einlesen ist irgendwie so... 1975.
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

ahhso ... ich hatte gehofft, dass ich ihm direkt sagen kann, dass er im Ersten Durchgang Byte 0 - 10.000.000, im 2. Durchgang Byte 9.999.900 - 20.000.000, u.s.w. einlesen soll. Denn dann wäre das mit dem überlappenden Suchstring kein Problem.

Na OK, ich versuchs mal mit Zeilenweise ... ich befürchte nur, dass mir das bei ner log-Datei mit 200MB und 1Mio Zeilen zu lange dauern wird ... na schaun wa mal.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Graf_Dracula hat geschrieben:ahhso ... ich hatte gehofft, dass ich ihm direkt sagen kann, dass er im Ersten Durchgang Byte 0 - 10.000.000, im 2. Durchgang Byte 9.999.900 - 20.000.000, u.s.w. einlesen soll. Denn dann wäre das mit dem überlappenden Suchstring kein Problem.
Das geht auch, musst du halt zurück `seek`en.

mkesper: Was genau meinst du jetzt damit?
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

Dauerbaustelle hat geschrieben: mkesper: Was genau meinst du jetzt damit?
Angenommen du hast eine Datei mit 50 Byte, die folgendermaßen ausieht:

aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee

Wenn man sich jetzt Blöcke mit je 15 Byte herausschneiden und untersuchen würde, würde man die folgenden Byteblöcke durchsuchen:

aaaaaaaaaabbbbb
bbbbbcccccccccc
ddddddddddeeeee
eeeee

Wäre der Suchstring jetzt z.B. "bbbbbbbbbb", würde dieser eben nicht gefunden werden.


------------------------------------------------------------------------------------------------------------
Das mit den aufgeteilten Dateien geht zwar soweit, aber offensichtlich nimmt er doch nicht alles auf einmal, was ich ihn anweise. Allein schon aufgrund der Geschwindigkeit soll er immer 50MB-Stücke durchsuchen. Jetzt habe ich aber festgestellt, dass er sich gar keine 50MB bei stream= file.read(50000000) reinlädt, sondern er nimmt einfach weniger, und sagt das vor allem nicht. Das, was ich dann Stückchenweise durchsuche ist auf jeden Fall nicht die komplette Datei. Was läuft da schon wieder schief ?
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Graf_Dracula hat geschrieben:Das mit den aufgeteilten Dateien geht zwar soweit, aber offensichtlich nimmt er doch nicht alles auf einmal, was ich ihn anweise. Allein schon aufgrund der Geschwindigkeit soll er immer 50MB-Stücke durchsuchen. Jetzt habe ich aber festgestellt, dass er sich gar keine 50MB bei stream= file.read(50000000) reinlädt, sondern er nimmt einfach weniger, und sagt das vor allem nicht. Das, was ich dann Stückchenweise durchsuche ist auf jeden Fall nicht die komplette Datei. Was läuft da schon wieder schief ?
Es ist nicht garantiert, dass `read` genau so viel liest wie angegeben. Der Parameter ist ein Maximalwert. Du musst einfach so lange lesen, bis du genug Daten hast.
Graf_Dracula
User
Beiträge: 20
Registriert: Donnerstag 17. Februar 2011, 16:05

Nein .... die eine Datei ist z.B. definitiv 27MB groß. Wenn ich stream= file.read(5000000) mache, rechnet er mir das vorher auch richtig aus, dass es 6 Stückchen werden und dann versucht er die 5MB einzulesen, aber irgendwas geht da mächtig schief. Lese ich immer nur 1MB ein, siehts besser aus, obwohl ich mir noch nicht ganz sicher bin, ob die 1MB auch wirklich richtig eingelesen werden. Ich speicher die Fragmente jetzt mal in eine extra Datei und schau mir das Ergebnis mal an ...
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Ich sagte doch: Es wird nicht garantiert, dass immer genau so viele Bytes gelesen werden, wie du an ``read`` übergibts. Es ist nur sichergestellt, dass maximal so viele Bytes gelesen werden.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Entschuldigung wenn ich da irgendwas falsch verstanden habe, aber dir ging es doch um die Durchsuchung einer Text-Datei und nicht um irgendeine Byte Phrase, oder ?

Was spricht also spricht gegen zeilenweise Iteration ?
Das es zu langer dauert - Wieso glaubst du das du mit einem zusammen wurschteln der Daten effizienter bist?
Du kannst genauso gut die Zeilen auch so lange auslesen, bis du eine gewisse Größe erreicht hast und dann darin suchen. Wieso also mit den Bytes rumbasteln wo man dann doch mal die Mitte eines Wortes/Satzes erwischen kann?

@Dauerbaustelle sollte man die Datei nicht auch wieder schließen? -oder muss eine aus dem Zipfile Object geöffnete Datei nicht wieder geschlossen werden ?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Xynon1 hat geschrieben:Entschuldigung wenn ich da irgendwas falsch verstanden habe, aber dir ging es doch um die Durchsuchung einer Text-Datei und nicht um irgendeine Byte Phrase, oder ?

Was spricht also spricht gegen zeilenweise Iteration ?
Eine Text-Datei ist auch nur ein Haufen Bytes. Und ich habe nirgendwo den Hinweis gefunden, dass er/sie immer nur zeilenweise suchen muss. Das Pattern könnte ja auch über mehrere Zeilen verteilt sein. Außerdem zielte meine Antwort darauf ab, zu erklären, warum ``read`` nicht immer so viele Bytes zurückgibt, wie man gerne hätte.
@Dauerbaustelle sollte man die Datei nicht auch wieder schließen? -oder muss eine aus dem Zipfile Object geöffnete Datei nicht wieder geschlossen werden ?
Keine Ahnung, wie das mit der ziplib ist. Hab ich noch nie verwendet. Das war ja nur ein kleiner Hinweis und kein funktionierendes Beispiel.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ich weiß schon das Textdateien nur Bytes sind, und ich mach dir ja keinen Vorwurf ihm das Byteweise lesen erwähnt zu haben, nur das er sich daran "festbeißt" versteh ich nicht.

Offensichtlich wenn das richtig entnommen habe versuch er möglichst große Blöcke auszulesen, aber nicht zu Große. Und darin sucht er jetzt einen String, welcher wie schon oben Bemerkt wurde auch in zwei teile zerlegt werden kann bei einem solchen auslesen.
Wieso dann nicht, Zeilen bis zu einer bestimmten Größe auslesen das Risiko, das ein eventueller Umbruch drin ist, ist genauso groß wie bei dem Byteweise lesen. Nur hier hat man dann wenigsten nicht das Risiko, das sogar die Zeile oder ein Wort darin einfach zerlegt wird.

Es wäre überhaupt mal Sinnvoll zu erwähnen was denn nun exakt gesucht wird.


Und ich schließe mal daraus http://docs.python.org/library/zipfile. ... le-objects, das man zumindest das ZipFile Object schließen muss.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Antworten