Chunkweises Lesen großer Dateien
Verarbeiten Sie Dateien, die den RAM übersteigen, indem Sie sie mit chunksize in read_csv blockweise einlesen und die Ergebnisse schrittweise aggregieren.
Chunkweises Lesen großer Dateien ist eine kostenlose Pandas & NumPy Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Pandas & NumPy Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Pandas & NumPy Academy-Kurs umfasst insgesamt 4 Lektionen.
Wenn Dateien den Arbeitsspeicher überschreiten
Ein häufiges Nadelöhr in Produktionsdatenpipelines ist eine CSV-Datei, die größer ist als der verfügbare Arbeitsspeicher. Wenn eine Datei 20 GB groß ist und der Rechner über 16 GB RAM verfügt, stürzt pd.read_csv('file.csv') mit einem MemoryError ab. Die Lösung ist das Lesen in Blöcken: Laden Sie die Datei in Blöcken fester Größe, verarbeiten Sie jeden Block und sammeln Sie die Ergebnisse. So können Sie beliebig große Dateien analysieren, ohne sie vollständig in den Arbeitsspeicher zu laden.
import pandas as pd
import numpy as np
# Simulate a large CSV by writing one
np.random.seed(0)
sample = pd.DataFrame({
'date': pd.date_range('2023-01-01', periods=100000, freq='h'),
'region': np.random.choice(['North','South','East','West'], 100000),
'sales': np.random.randint(100, 1000, 100000)
})
sample.to_csv('/tmp/large_sales.csv', index=False)
print(f'File size: {pd.io.common.get_handle("/tmp/large_sales.csv", "r").handle.seek(0, 2)/1e6:.1f} MB... (simulated)')
print('Rows:', len(sample))Der Parameter chunksize in read_csv
Übergeben Sie chunksize=n an pd.read_csv(), damit statt eines DataFrames ein TextFileReader-Iterator zurückgegeben wird. Jede Iteration liefert die nächsten n Zeilen als DataFrame. Dadurch befinden sich jeweils nur n Zeilen im Arbeitsspeicher. Ein guter Ausgangswert für chunksize sind 100.000 Zeilen — klein genug, um in den RAM zu passen, aber groß genug, um den I/O-Overhead überschaubar zu halten. Passen Sie den Wert an den verfügbaren RAM und die Anzahl der Spalten an.
import pandas as pd
# Read file in chunks of 25,000 rows
chunk_iter = pd.read_csv('/tmp/large_sales.csv', chunksize=25000)
# Peek at the first chunk
first_chunk = next(chunk_iter)
print('First chunk shape:', first_chunk.shape)
print(first_chunk.head(3))Über Blöcke iterieren
Verwenden Sie eine for-Schleife über den Block-Iterator, um jeden Block zu verarbeiten. Bei einfachen Operationen wie dem Zählen von Zeilen, dem Summieren einer Spalte oder dem Filtern verarbeiten Sie jeden Block unabhängig und sammeln die Ergebnisse in einer Liste oder einer laufenden Summe. Verwenden Sie den Iterator immer innerhalb einer with-Anweisung oder erstellen Sie ihn für jeden Pipeline-Lauf neu — Iteratoren werden einmalig verbraucht und können nicht neu gestartet werden.
import pandas as pd
total_rows = 0
total_sales = 0.0
chunk_count = 0
for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
total_rows += len(chunk)
total_sales += chunk['sales'].sum()
chunk_count += 1
print(f'Chunks processed: {chunk_count}')
print(f'Total rows: {total_rows:,}')
print(f'Total sales: {total_sales:,.0f}')
print(f'Avg sales per row: {total_sales/total_rows:.2f}')Zeilen beim Lesen in Blöcken filtern
Wenden Sie Zeilenfilter innerhalb der Schleife an, um nicht benötigte Daten zu verwerfen, bevor sie sich ansammeln. So bleibt der Speicherverbrauch niedrig, da nur Zeilen behalten werden, die Ihren Kriterien entsprechen. Um beispielsweise alle Zeilen der Region „North“ aus einer 10-GB-Datei zu extrahieren, filtern Sie jeden Block, bevor Sie ihn an Ihre Ergebnisliste anhängen. Das abschließende pd.concat verarbeitet dann nur die gefilterte Teilmenge, die deutlich kleiner ist.
import pandas as pd
filtered_chunks = []
for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
# Keep only North region rows
north = chunk[chunk['region'] == 'North']
if len(north) > 0:
filtered_chunks.append(north)
north_df = pd.concat(filtered_chunks, ignore_index=True)
print(f'North region rows: {len(north_df):,}')
print(f'North total sales: {north_df["sales"].sum():,.0f}')Inkrementelle GroupBy-Aggregation
GroupBy-Aggregationen über mehrere Blöcke sind schwieriger als einfache Summen, da sich Gruppen über mehrere Blöcke erstrecken können. Das Vorgehen lautet: Berechnen Sie für jeden Block Gruppensummen und -anzahlen, verketten Sie diese Teilergebnisse und führen Sie anschließend ein abschließendes groupby über den gesammelten Teilergebnissen aus. Rufen Sie niemals pro Block groupby().mean() auf und bilden Sie anschließend den Durchschnitt der Durchschnitte — das liefert falsche Ergebnisse, wenn sich die Gruppengrößen zwischen den Blöcken unterscheiden.
import pandas as pd
partials = []
for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
# Compute sum and count per region in this chunk
partial = chunk.groupby('region')['sales'].agg(['sum', 'count'])
partials.append(partial)
# Combine all partial results
combined = pd.concat(partials).groupby(level=0).sum()
combined['mean'] = combined['sum'] / combined['count']
print('Regional aggregation (chunked):')
print(combined.round(2))Speichereffiziente Typen beim Laden festlegen
Reduzieren Sie den Speicherverbrauch beim blockweisen Laden, indem Sie die dtypes der Spalten bereits in read_csv festlegen. So verhindert man, dass Pandas für jeden Block zunächst breite Typen reserviert und diese anschließend verwirft. Übergeben Sie ein Dictionary wie dtype={'region': 'category', 'sales': 'int32'} an read_csv(). Zusammen mit dem Lesen in Blöcken kann dies den Spitzenverbrauch auf weniger als 10 % des naiven Ladens der vollständigen Datei reduzieren.
import pandas as pd
specified_dtypes = {
'region': 'category',
'sales': 'int32'
}
total_sales = 0
for chunk in pd.read_csv(
'/tmp/large_sales.csv',
chunksize=25000,
dtype=specified_dtypes,
parse_dates=['date']
):
total_sales += chunk['sales'].sum()
# Only 25k rows * (category + int32 + datetime) in RAM at once
print(f'Total sales (memory-efficient): {total_sales:,.0f}')Ergebnisse schrittweise schreiben
Wenn die Verarbeitungsergebnisse jedes Blocks ebenfalls in eine Datei geschrieben werden müssen, schreiben Sie jeden verarbeiteten Block direkt, statt alles im Arbeitsspeicher zu sammeln. Verwenden Sie mode='a' (Anhängen) und nach dem ersten Block header=False mit to_csv(). Dadurch bleiben sowohl der Speicherbedarf für die Eingabe als auch für die Ausgabe auf die Blockgröße begrenzt. So kann die Pipeline beliebig große Dateien auf einem Rechner mit begrenztem Arbeitsspeicher verarbeiten.
import pandas as pd
import os
output_path = '/tmp/filtered_output.csv'
# Remove previous output if it exists
if os.path.exists(output_path):
os.remove(output_path)
first_chunk = True
for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=25000):
# Process: keep only high-value rows
processed = chunk[chunk['sales'] > 800].copy()
# Write: header only on first chunk, append thereafter
processed.to_csv(output_path,
mode='a',
header=first_chunk,
index=False)
first_chunk = False
result = pd.read_csv(output_path)
print(f'High-value rows written: {len(result):,}')
print(f'Average sales (>800): {result["sales"].mean():.1f}')Einführung in Dask als direkte Alternative
Dask stellt eine Pandas-ähnliche API bereit, die Operationen verzögert und automatisch parallel über mehrere Blöcke hinweg ausführt. Statt eine manuelle Schleife für Blöcke zu schreiben, verwenden Sie dask_df = dd.read_csv('file.csv') und anschließend dieselben Pandas-Operationen — groupby, filter, merge. Rufen Sie am Ende .compute() auf, um die Ausführung zu starten. Dask ist die praktischste Lösung, wenn Ihre Pipeline komplexe mehrstufige Operationen umfasst, die sich nur schwer manuell mit Blockverarbeitung umsetzen lassen.
# pip install dask
# import dask.dataframe as dd
# Read the large CSV as a Dask DataFrame (lazy — no data loaded yet)
# ddf = dd.read_csv('/tmp/large_sales.csv')
# Operations are lazy — no computation happens until .compute()
# result = ddf.groupby('region')['sales'].mean().compute()
# print(result)
# Key Dask advantages:
# - Automatic chunking (no manual chunksize loops)
# - Parallel execution (multi-core)
# - Familiar Pandas API
# - Works with files larger than RAM
print('Dask extends Pandas to datasets larger than RAM with minimal API changes.')Die Blockgröße auswählen
Die ideale Blockgröße gleicht zwei gegensätzliche Faktoren aus: zu klein (z. B. 1.000 Zeilen) verursacht einen hohen Overhead pro Block (Einrichtung der Dateieingabe und Erstellung des DataFrames), wodurch die Schleife länger dauert. Zu groß (z. B. 10 Mio. Zeilen) verfehlt den Zweck, weil zu viele Daten auf einmal in den RAM geladen werden. Ein praktikabler Ausgangspunkt sind Blöcke mit 50–200 MB im Arbeitsspeicher. Bei einem DataFrame mit 10 Spalten, die durchschnittlich jeweils 8 Bytes benötigen, entsprechen 100.000 Zeilen etwa 8 MB pro Block — ein sicherer Standardwert, der ausreichend Spielraum lässt.
import pandas as pd
import timeit
# Benchmark different chunk sizes
for chunksize in [10000, 50000, 100000]:
t = timeit.timeit(
lambda: sum(chunk['sales'].sum()
for chunk in pd.read_csv('/tmp/large_sales.csv', chunksize=chunksize)),
number=3
)
print(f'chunksize={chunksize:>7,}: {t/3:.3f}s per pass')Parquet oder CSV für große Datenmengen
Wenn Sie das Dateiformat bestimmen können, bevorzugen Sie für große Datensätze Parquet gegenüber CSV. Parquet ist ein spaltenorientiertes Binärformat, das angeforderte Spalten allein lädt (Spaltenauswahl), deutlich besser als CSV komprimiert, Dtypes erhält (keine erneute Typbestimmung beim Laden) und 5- bis 20-mal schneller liest als eine entsprechende CSV-Datei. Konvertieren Sie eine große CSV-Datei einmalig mit pd.read_csv('file.csv', chunksize=500000) + to_parquet in Parquet und verwenden Sie anschließend für alle weiteren Lesevorgänge pd.read_parquet(columns=['col1','col2']).
import pandas as pd
# Convert our CSV to Parquet (do this once)
df = pd.read_csv('/tmp/large_sales.csv', parse_dates=['date'])
df['region'] = df['region'].astype('category')
df['sales'] = df['sales'].astype('int32')
df.to_parquet('/tmp/large_sales.parquet', index=False)
# Now read only the columns needed — much faster than CSV
sales_by_region = pd.read_parquet(
'/tmp/large_sales.parquet',
columns=['region', 'sales']
)
print('Parquet read result:')
print(sales_by_region.groupby('region')['sales'].mean().round(1))
print('\ndtypes preserved:', sales_by_region.dtypes.to_dict())Vollständiges Muster für eine Pipeline mit Blockverarbeitung
Ein vollständiges Muster für die Verarbeitung großer Dateien: 1) Legen Sie die Dtypes bereits beim Lesen fest. 2) Filtern Sie Zeilen innerhalb der Schleife so früh wie möglich. 3) Berechnen Sie für jeden Block Teilergebnisse (Summe + Anzahl, niemals direkt den Mittelwert). 4) Führen Sie nach der Schleife die Teilergebnisse zusammen und berechnen Sie die endgültigen Statistiken. 5) Schreiben Sie die Ausgabe schrittweise, wenn die Ergebnisse groß sind. Dieses Muster verarbeitet Dateien beliebiger Größe auf jedem Rechner, sofern die chunksize passend abgestimmt ist.
Schnelltest
Testen Sie Ihr Verständnis des blockweisen Lesens aus dieser Lektion.
Zusammenfassung der Lektion
In dieser Lektion haben Sie gelernt: chunksize in read_csv gibt einen Iterator zurück, der einen DataFrame pro Block liefert, sodass Dateien verarbeitet werden können, die größer als der RAM sind, Teilsummen (Summe + Anzahl) lassen sich über mehrere Blöcke hinweg korrekt zusammenführen, während Mittelwerte nicht direkt gemittelt werden dürfen, und das Parquet-Format ist aufgrund seiner Komprimierung, Geschwindigkeit und Fähigkeit, Dtypes zu erhalten, langfristig die beste Alternative zu CSV für große Datensätze. Damit ist der Kurs „Pandas Performance Tips“ abgeschlossen — Sie sind bereit für die fortgeschrittenen B2-Kurse!
Lerne Python mit einem KI-Tutor — kostenlos
Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.
- Kurse
- 30
- Lektionen
- 120
Häufig gestellte Fragen
Ist die Lektion „Chunkweises Lesen großer Dateien“ kostenlos?
Ja — der vollständige Text von „Chunkweises Lesen großer Dateien“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Pandas & NumPy Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Pandas & NumPy Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Chunkweises Lesen großer Dateien“?
Verarbeiten Sie Dateien, die den RAM übersteigen, indem Sie sie mit chunksize in read_csv blockweise einlesen und die Ergebnisse schrittweise aggregieren. Du übst Pandas & NumPy Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Pandas & NumPy Academy zu starten?
Keine Vorkenntnisse erforderlich. Pandas & NumPy Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Chunkweises Lesen großer Dateien“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Pandas & NumPy Academy-Lektion Code schreiben und ausführen?
Ja. Jede Pandas & NumPy Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Profiling mit timeit und memory_profiler
- iterrows und Python-Schleifen vermeiden
- Effiziente Datentypen zur Speicherreduzierung
- Chunkweises Lesen großer Dateien