sql >> Databasteknik >  >> RDS >> PostgreSQL

MemoryError när du använder metoden read() vid läsning av en stor JSON-fil från Amazon S3

En betydande besparing kan göras genom att undvika att slurpa in hela din indatafil i minnet som en list rader.

Specifikt är dessa rader hemska för minnesanvändning, eftersom de involverar en maximal minnesanvändning på bytes objekt storleken på hela filen, plus en list rader med hela innehållet i filen också:

file_content = obj['Body'].read().decode('utf-8').splitlines(True)
for line in file_content:

För en 1 GB ASCII-textfil med 5 miljoner rader, på 64-bitars Python 3.3+, är det ett maximalt minneskrav på ungefär 2,3 GB för bara bytes objekt, list , och den individuella str s i list . Ett program som behöver 2,3 gånger så mycket RAM-minne som storleken på de filer det bearbetar kommer inte att skalas till stora filer.

För att fixa, ändra den ursprungliga koden till:

file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
for line in file_content:

Med tanke på att obj['Body'] verkar vara användbar för lat streaming detta bör ta bort båda kopior av hela fildata från minnet. Använda TextIOWrapper betyder obj['Body'] läses lätt och avkodas i bitar (av några kB åt gången), och raderna upprepas också lätt; detta minskar minnesbehovet till en liten, i stort sett fast mängd (den maximala minneskostnaden beror på längden på den längsta raden), oavsett filstorlek.

Uppdatering:

Det ser ut som StreamingBody implementerar inte io.BufferedIOBase ABC. Den har sin egen dokumenterade API men det kan användas för liknande ändamål. Om du inte kan skapa TextIOWrapper gör jobbet åt dig (det är mycket effektivare och enklare om det kan fås att fungera), ett alternativ skulle vara att göra:

file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
for line in file_content:

Till skillnad från att använda TextIOWrapper , det gynnas inte av bulkavkodning av block (varje rad avkodas individuellt), men annars bör den fortfarande uppnå samma fördelar i form av minskad minnesanvändning.




  1. SQLite-minnesproblem med singleton-metoden

  2. Ansluta till MySQL från Eclipse (CDT)

  3. Välja en kolumn som också är ett nyckelord i MySQL

  4. Kör uppsättning SQL-frågor med batchfil?