Významné úspory lze dosáhnout tím, že se vyhnete tomu, že celý vstupní soubor budete dávat do paměti jako list
řádků.
Konkrétně tyto řádky jsou hrozné na využití paměti, protože zahrnují maximální využití paměti bytes
objekt velikosti celého vašeho souboru plus list
řádků s úplným obsahem souboru:
file_content = obj['Body'].read().decode('utf-8').splitlines(True)
for line in file_content:
Pro 1 GB textový soubor ASCII s 5 miliony řádků v 64bitovém Pythonu 3.3+ to představuje špičkový požadavek na paměť zhruba 2,3 GB za jen bytes
objekt, list
a jednotlivé str
s v list
. Program, který potřebuje 2,3x více paměti RAM, než je velikost souborů, které zpracovává, se nebude škálovat na velké soubory.
Chcete-li to opravit, změňte původní kód na:
file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
for line in file_content:
Vzhledem k tomu, že obj['Body']
se zdá být použitelný pro líné streamování
toto by mělo odstranit obojí kopie úplných dat souboru z paměti. Pomocí TextIOWrapper
znamená obj['Body']
se líně čte a dekóduje po částech (několik KB najednou) a řádky se také líně iterují; to snižuje nároky na paměť na malé, převážně pevné množství (špičková cena paměti by závisela na délce nejdelšího řádku), bez ohledu na velikost souboru.
Aktualizace:
Vypadá to jako StreamingBody
neimplementuje io.BufferedIOBase
ABC. Má své vlastní zdokumentované API
i když to lze použít pro podobný účel. Pokud nemůžete vytvořit TextIOWrapper
dělat práci za vás (je to mnohem efektivnější a jednodušší, pokud se to dá udělat), alternativou by bylo udělat:
file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
for line in file_content:
Na rozdíl od použití TextIOWrapper
, netěží z hromadného dekódování bloků (každý řádek je dekódován samostatně), ale jinak by měl stále dosahovat stejných výhod ve smyslu snížení využití paměti.