En betydelig besparelse kan opnås ved at undgå at slurre hele din inputfil i hukommelsen som en list
af linjer.
Specifikt er disse linjer forfærdelige med hensyn til hukommelsesbrug, idet de involverer en maksimal hukommelsesbrug på bytes
objekt størrelsen af hele din fil, plus en list
af linjer med det komplette indhold af filen også:
file_content = obj['Body'].read().decode('utf-8').splitlines(True)
for line in file_content:
For en 1 GB ASCII-tekstfil med 5 millioner linjer, på 64 bit Python 3.3+, er det et maksimalt hukommelseskrav på ca. 2,3 GB for kun bytes
objekt, list
, og den individuelle str
s på list
. Et program, der har brug for 2,3 gange så meget RAM som størrelsen af de filer, det behandler, skaleres ikke til store filer.
For at rette, skal du ændre den originale kode til:
file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
for line in file_content:
I betragtning af at obj['Body']
ser ud til at kunne bruges til dovne streaming
dette burde fjerne begge kopier af de komplette fildata fra hukommelsen. Brug af TextIOWrapper
betyder obj['Body']
læses dovent og afkodes i bidder (af nogle få KB ad gangen), og linjerne gentages også dovent; dette reducerer hukommelsesbehovet til et lille, stort set fast beløb (den maksimale hukommelsesomkostning vil afhænge af længden af den længste linje), uanset filstørrelsen.
Opdatering:
Det ligner StreamingBody
implementerer ikke io.BufferedIOBase
ABC. Den har sin egen dokumenterede API
det kan dog bruges til et lignende formål. Hvis du ikke kan lave TextIOWrapper
gøre arbejdet for dig (det er meget mere effektivt og enkelt, hvis det kan fås til at fungere), et alternativ ville være at gøre:
file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
for line in file_content:
I modsætning til at bruge TextIOWrapper
, den har ikke gavn af masseafkodning af blokke (hver linje afkodes individuelt), men ellers skulle den stadig opnå de samme fordele i form af reduceret hukommelsesforbrug.