Kursinhalt
Optimierungstechniken in Python
Optimierungstechniken in Python
Umgang Mit Großen Dateien
Das effiziente Verarbeiten großer Dateien ist entscheidend, wenn man mit Datensätzen arbeitet, die zu groß sind, um in den Speicher zu passen. Python bietet Werkzeuge wie open()
und map()
, die es ermöglichen, Dateien lazy zu verarbeiten, was Speicher spart und die Leistung verbessert.
Was sind Iteratoren?
Bevor wir mit der open()
-Funktion fortfahren, sollten wir zuerst verstehen, was ein Iterator ist. Ein Iterator ist ein Objekt, das einen Datenstrom darstellt und es Ihnen ermöglicht, ein Element nach dem anderen zuzugreifen. Iteratoren implementieren zwei Methoden:
__iter__()
: gibt das Iterator-Objekt selbst zurück;__next__()
: gibt das nächste Element im Strom zurück und löst eineStopIteration
-Ausnahme aus, wenn keine Elemente mehr vorhanden sind.
Angenommen, wir haben einen Iterator namens iterator_object
. Wir können über ihn mit einer üblichen for
-Schleife iterieren:
Tatsächlich passiert im Hintergrund Folgendes (die next()
-Funktion ruft intern die __next__()
-Methode des Iterators auf):
Im Gegensatz zu Standardkollektionen sind Iteratoren durch lazy evaluation gekennzeichnet, was bedeutet, dass sie Daten nur bei Bedarf erzeugen oder abrufen, anstatt alles auf einmal in den Speicher zu laden. Dieser Ansatz macht sie besonders speichereffizient, insbesondere beim Arbeiten mit großen Datensätzen.
Dateiobjekte als Iteratoren
Die open()
-Funktion gibt ein Dateiobjekt zurück, das ein Iterator ist. Dies ermöglicht Ihnen:
- Über eine Datei Zeile für Zeile mit einer
for
-Schleife zu iterieren; - Eine Zeile nach der anderen in den Speicher zu lesen, was es für große Dateien geeignet macht (solange einzelne Zeilen in den Speicher passen).
Zum Beispiel, wenn eine Protokolldatei mit 1,000,000
Zeilen sowohl INFO
- als auch ERROR
-Nachrichten enthält, können wir dennoch ERROR
-Vorkommen zählen, indem wir die Datei Zeile für Zeile durchgehen, selbst wenn die Datei nicht vollständig in den Speicher passt (was der Fall sein wird, wenn wir noch mehr Protokolle hinzufügen).
log_lines = [f"INFO: Log entry {i}" if i % 100 != 0 else f"ERROR: Critical issue {i}" for i in range(1, 1000001)] with open("large_log.txt", "w") as log_file: log_file.write("\n".join(log_lines)) # Process the file to count error entries error_count = 0 for line in open("large_log.txt"): if "ERROR" in line: error_count += 1 print(f"Total error entries: {error_count}")
Transformieren von Dateizeilen mit map()
Wie im vorherigen Kapitel erwähnt, gibt map()
einen Iterator zurück, der eine Transformationsfunktion faul auf jede Zeile in einer Datei anwendet. Ähnlich wie Dateiobjekte verarbeitet map()
Daten ein Element nach dem anderen, ohne alles in den Speicher zu laden, was es zu einer effizienten Option für die Verarbeitung großer Dateien macht.
Zum Beispiel erstellen wir eine Datei mit 1000000
E-Mail-Adressen, von denen einige Großbuchstaben enthalten. Unser Ziel ist es, alle E-Mails in Kleinbuchstaben umzuwandeln und die normalisierten Ergebnisse in einer neuen Datei ('normalized_emails.txt'
) zu speichern. Wir verwenden map()
, um dies zu erreichen und sicherzustellen, dass das Skript effizient bleibt und auch für die Verarbeitung noch größerer Dateien geeignet ist.
# Create a file with mixed-case email addresses email_lines = [ "John.Doe@example.com", "Jane.SMITH@domain.org", "BOB.brown@anotherexample.net", "ALICE.williams@sample.com" ] * 250000 # Repeat to simulate a large file with open("email_list.txt", "w") as email_file: email_file.write("\n".join(email_lines)) # Process the file to standardize email addresses (convert to lowercase) with open("email_list.txt") as input_file, open("normalized_emails.txt", "w") as output_file: # Use map() to convert each email to lowercase lowercase_emails = map(str.lower, input_file) for email in lowercase_emails: output_file.write(email) # Print the last email to verify the results print(email) print('Done')
1. Sie müssen alle E-Mail-Adressen in einer Datei in Kleinbuchstaben umwandeln und in einer neuen Datei speichern, ohne alles in den Speicher zu laden. Welche Vorgehensweise ist am effizientesten?
2. Welche der folgenden Aussagen über Dateiobjekte ist korrekt?
Danke für Ihr Feedback!