Die meisten effizienten Art und Weise, in Python Iteration über eine große Datei (10GB+)
Arbeite ich an einem Python-Skript Durchlaufen Sie zwei Dateien - die eine enthält eine Liste von UUIDs, die andere mit einer großen Menge der log-Einträge - jede Zeile mit der Uuid aus der anderen Datei. Der Zweck des Programms ist die Erstellung einer Liste der UUIDS aus Datei1, dann für jedes mal, dass die UUID gefunden wird in der log-Datei, erhöhen Sie den zugehörigen Wert für jedes mal, wenn eine übereinstimmung gefunden wird.
Also lange Geschichte kurz, zu zählen, wie oft jede UUID erscheint in der log-Datei.
Im moment habe ich eine Liste die aufgefüllt wird mit der UUID als Schlüssel und "trifft zu" als Wert. Dann eine weitere Schleife, die durchläuft jede Zeile der log-Datei, und überprüfen, ob die UUID in der log entspricht einer UUID UUID in der Liste. Wenn es passt, erhöht es den Wert.
for i, logLine in enumerate(logHandle): #start matching UUID entries in log file to UUID from rulebase
if logFunc.progress(lineCount, logSize): #check progress
print logFunc.progress(lineCount, logSize) #print progress in 10% intervals
for uid in uidHits:
if logLine.count(uid) == 1: #for each UUID, check the current line of the log for a match in the UUID list
uidHits[uid] += 1 #if matched, increment the relevant value in the uidHits list
break #as we've already found the match, don't process the rest
lineCount += 1
Es funktioniert wie es sollte - aber ich bin mir sicher, dass es eine effizientere Art und Weise der Verarbeitung der Datei. Ich habe durch ein paar guides und festgestellt, dass mit 'count' ist schneller als ein regex kompiliert. Ich dachte, Lesen von Dateien in chunks anstatt Zeile für Zeile würde die Leistung verbessern, indem die Verringerung der Menge an disk-I/O-Zeit, aber den Unterschied in der Leistung auf einem test-Datei ~200MB war vernachlässigbar. Wenn jemand noch andere Methoden wäre ich sehr dankbar 🙂
- Datei-I/O ist in der Regel gepuffert, unabhängig von der Größe der Stücke, die Sie tatsächlich Lesen.
- Braucht es, um noch effizienter zu werden? Wie lange dauert es? Wie lange brauchen Sie, es zu nehmen? Sie haben vielleicht schon schlagen Sie die performance-Grenze Ihres storage (disk), in dem Fall ist es egal, wie viel schneller Sie Ihre Python-Skript ist.
- Es läuft durch eine test-Datei jetzt - es ist auf halbem Weg durch eine 10 GB-Datei, und es ist etwa 30 Minuten. Meinen ersten Python-Ausflug ich weiß wirklich nicht, ob das schnell oder langsam. Es gibt keine Voraussetzung, für die es abgeschlossen ist in x Minuten, aber schneller ist besser 😉
- In Ihrem Beispiel ist die zweite wenn-Anweisung ist leer (kein code eingerückt, dass nach). Könnte man das lösen?
- ist jetzt behoben, sorry!
- Du wirst über alle UIDs für jede Zeile in der Datei. Stattdessen, finden Sie die UUID in jeder Zeile und nachschlagen in einem Wörterbuch. Versuchen so wenig wie möglich in den Teil des Codes, der wird immer genannt, am häufigsten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Denke, funktionell!
Schreiben Sie eine Funktion, die eine Zeile in der log-Datei und wieder die uuid. Rufen Sie
uuid
sagen.Anwendung dieser Funktion auf jede Zeile der log-Datei. Wenn Sie mit Python 3 können Sie die integrierte Funktion anzeigen; andernfalls müssen Sie mit itertools.imap.
Pass dieser iterator, um eine Sammlungen.Counter.
Diese werden dann ziemlich viel optimal effizient.
Ein paar Kommentare:
Diese ignoriert völlig die Liste der UUIDs und zählt nur diejenigen, die in der Protokolldatei angezeigt. Sie müssen das Programm verändern etwas, wenn Sie dies nicht möchten.
Wie die Leute oben gesagt haben, mit einer 10GB-Datei werden Sie wahrscheinlich auf die Grenzen Ihrer Festplatte ziemlich schnell. Für code-nur Verbesserungen, die generator-Beratung ist groß. In python 2.x es wird so Aussehen
Es klingt wie diesem tatsächlich nicht zu sein, ein python-problem. Wenn Sie nicht tun, nichts schwieriger als das zählen UUIDs, Unix, in der Lage sein könnte, Ihre Probleme zu lösen schneller als python kann.
Dies ist nicht ein 5-Linien-Antwort auf deine Frage, aber es war eine hervorragende Anleitung gegeben, auf PyCon'08 genannt Generator Tricks für System-Programmierer. Es gibt auch eine follow-up-tutorial genannt Eine Kuriose Natürlich auf Coroutinen und Parallelität.
Den Generator tutorial speziell verwendet große log-Datei Verarbeitung, seinem Beispiel.
Haben Sie versucht,mincemeat.py? Es ist eine Python-Implementierung des MapReduce distributed computing framework. Ich bin mir nicht sicher, ob Sie haben performance-Gewinn, da habe ich noch nicht verarbeitet 10GB Daten, bevor Sie es, wenn Sie vielleicht entdecken Sie in diesem Rahmen.
Führen Sie die Messung, wo die meisten Zeit verbracht wird, mit einem profiler http://docs.python.org/library/profile.html
Wo am besten optimieren wird, hängt von der Art Ihrer Daten: Wenn Sie die Liste der uuids ist nicht sehr lang, Sie können feststellen, zum Beispiel, dass ein großer Teil der Zeit verbringen Sie auf dem "wenn logFunc.Fortschritt(lineCount, logSize)". Wenn die Liste ist sehr lange, Sie könnte es helfen, das Ergebnis zu speichern, der
uidHits.keys()
auf eine variable außerhalb der Schleife und Durchlaufen, dass statt dem Wörterbuch selbst, sondern Rosh Oxymoron ist, was darauf hindeutet, finden Sie die id und erst dann die überprüfung für die es in uidHits würde wahrscheinlich noch mehr helfen.In jedem Fall, können Sie beseitigen die
lineCount
variable, und verwenden Siei
statt. Undfind(uid) != -1
könnte besser sein, alscount(uid) == 1
wenn die Linien sehr lang sind.