Des économies importantes peuvent être réalisées en évitant de mettre tout votre fichier d'entrée en mémoire sous forme de list
de lignes.
Plus précisément, ces lignes sont terribles sur l'utilisation de la mémoire, en ce sens qu'elles impliquent une utilisation maximale de la mémoire d'un bytes
objet la taille de votre fichier entier, plus une list
de lignes avec le contenu complet du fichier également :
file_content = obj['Body'].read().decode('utf-8').splitlines(True)
for line in file_content:
Pour un fichier texte ASCII de 1 Go avec 5 millions de lignes, sur Python 3.3+ 64 bits, il s'agit d'un besoin maximal en mémoire d'environ 2,3 Go pour seulement les bytes
objet, la list
, et la str
individuelle s dans la list
. Un programme qui a besoin de 2,3 fois plus de RAM que la taille des fichiers qu'il traite ne sera pas adapté aux fichiers volumineux.
Pour corriger, remplacez ce code d'origine par :
file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
for line in file_content:
Étant donné que obj['Body']
semble être utilisable pour le streaming paresseux
cela devrait supprimer les deux copies des données complètes du fichier à partir de la mémoire. Utilisation de TextIOWrapper
signifie obj['Body']
est lu et décodé paresseusement en morceaux (de quelques Ko à la fois), et les lignes sont également itérées paresseusement ; cela réduit les demandes de mémoire à une petite quantité largement fixe (le coût maximal de la mémoire dépend de la longueur de la ligne la plus longue), quelle que soit la taille du fichier.
Mise à jour :
Il ressemble à StreamingBody
n'implémente pas le io.BufferedIOBase
ABC. Il a sa propre API documentée
cependant, cela peut être utilisé à des fins similaires. Si vous ne pouvez pas créer le TextIOWrapper
faire le travail pour vous (c'est beaucoup plus efficace et simple si cela peut fonctionner), une alternative serait de faire :
file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
for line in file_content:
Contrairement à l'utilisation de TextIOWrapper
, il ne bénéficie pas du décodage en bloc des blocs (chaque ligne est décodée individuellement), mais sinon, il devrait toujours obtenir les mêmes avantages en termes de réduction de l'utilisation de la mémoire.