Python: Lesen Sie Zeilen aus komprimierten Textdateien

72

Ist es einfach, mit Python eine Zeile aus einer gz-komprimierten Textdatei zu lesen, ohne die Datei vollständig zu extrahieren? Ich habe eine text.gz-Datei, die ungefähr 200 MB groß ist. Wenn ich es extrahiere, wird es 7,4 GB. Und dies ist nicht die einzige Datei, die ich lesen muss. Für den gesamten Prozess muss ich 10 Dateien lesen. Obwohl dies ein sequentieller Job sein wird, denke ich, dass es eine kluge Sache sein wird, dies zu tun, ohne die gesamten Informationen zu löschen. Ich weiß nicht einmal, dass es möglich ist. Wie geht das mit Python? Ich muss eine Textdatei Zeile für Zeile lesen.

delete_this_account
quelle

Antworten:

90

Verwenden von gzip.GzipFile :

import gzip

with gzip.open('input.gz','rt') as f:
    for line in f:
        print('got line', line)

Hinweis: gzip.open(filename, mode)ist ein Alias ​​für gzip.GzipFile(filename, mode). Ich bevorzuge das erstere, da es ähnlich aussieht wie with open(...) as f:das Öffnen unkomprimierter Dateien.

fferri
quelle
37
Für Python3 müssen Sie die zu öffnende Datei in 'rt' angeben, da 'r' standardmäßig binäres Lesen verwendet.
Kap
51

Sie können das Standard-gzip-Modul in Python verwenden. Benutz einfach:

gzip.open('myfile.gz')

um die Datei wie jede andere Datei zu öffnen und ihre Zeilen zu lesen.

Weitere Informationen hier: Python gzip Modul

Smichak
quelle
4
Lädt dies aus Neugier die gesamte Datei in den Speicher? Oder ist es klug genug, Leitungen nach Bedarf zu laden?
Sachinruk
2
@Sachin_ruk dies lädt die Datei nicht, es öffnet sie nur. Um die Daten tatsächlich aus der Datei zu laden, müssen Sie `` `f.readline ()` `ausführen, um jeweils eine Zeile zu lesen. Oder f.readlines(N)wo Nist die Anzahl der Zeilen, die Sie lesen möchten.
Tom
1

Die gzip-Bibliothek verwendet (offensichtlich) gzip, was etwas langsam sein kann. Sie können die Dinge mit einem Systemaufruf an pigz , der parallelisierten Version von , beschleunigengzip . Die Nachteile sind, dass Sie installieren müssen pigzund es während des Laufs mehr Kerne benötigt, aber es ist viel schneller und nicht speicherintensiver. Der Aufruf der Datei wird dann os.popen('pigz -dc ' + filename)statt gzip.open(filename,'rt'). Die Pigz-Flags dienen -dzur Dekomprimierung und -czur Standardausgabe, die dann abgerufen werden können os.popen.

Der folgende Code nimmt eine Datei und eine Nummer (1 oder 2) auf und zählt die Anzahl der Zeilen in der Datei mit den verschiedenen Aufrufen, während die Zeit gemessen wird, die der Code benötigt. Definieren Sie den folgenden Code in unzip-file.py:

#!/usr/bin/python
import os
import sys
import time
import gzip

def local_unzip(obj):
    t0 = time.time()
    count = 0
    with obj as f:
        for line in f:
            count += 1
    print(time.time() - t0, count)

r = sys.argv[1]
if sys.argv[2] == "1":
    local_unzip(gzip.open(r,'rt'))
else:
    local_unzip(os.popen('pigz -dc ' + r))

Der Aufruf dieser mit , /usr/bin/time -f %Mwelche Maßnahmen die maximale Speichernutzung des Prozesses auf einer 28G - Datei erhalten wir:

$ /usr/bin/time -f %M ./unzip-file.py $file 1
(3037.2604110240936, 1223422024)
5116

$ /usr/bin/time -f %M ./unzip-file.py $file 2
(598.771901845932, 1223422024)
4996

Dies zeigt, dass der Systemaufruf etwa fünfmal schneller ist (10 Minuten im Vergleich zu 50 Minuten), wenn im Grunde derselbe maximale Speicher verwendet wird. Es ist auch erwähnenswert, dass je nachdem, was Sie pro Zeile tun, das Lesen in der Datei möglicherweise nicht der begrenzende Faktor ist. In diesem Fall spielt die von Ihnen gewählte Option keine Rolle.

Cão
quelle