J'utilise Python 2.6 sur un Mac Mini avec 1 Go de RAM. Je veux lire dans un grand fichier textePython: Comment lire un énorme fichier texte en mémoire
$ ls -l links.csv; file links.csv; tail links.csv
-rw-r--r-- 1 user user 469904280 30 Nov 22:42 links.csv
links.csv: ASCII text, with CRLF line terminators
4757187,59883
4757187,99822
4757187,66546
4757187,638452
4757187,4627959
4757187,312826
4757187,6143
4757187,6141
4757187,3081726
4757187,58197
Ainsi, chaque ligne dans le fichier se compose d'un tuple de deux valeurs séparées par des virgules entières. Je veux lire dans le fichier entier et le trier selon la deuxième colonne. Je sais, que je pourrais faire le tri sans lire le dossier entier dans la mémoire. Mais je pensais pour un fichier de 500 Mo que je devrais quand même pouvoir le faire en mémoire puisque j'ai 1 Go disponible.
Toutefois, lorsque j'essaie de lire dans le fichier, Python semble allouer beaucoup plus de mémoire que ce qui est nécessaire pour le fichier sur le disque. Donc, même avec 1 Go de RAM, je ne suis pas en mesure de lire dans le fichier de 500 Mo en mémoire. Mon code Python pour lire le fichier et l'impression des informations sur la consommation de mémoire est:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
infile=open("links.csv", "r")
edges=[]
count=0
#count the total number of lines in the file
for line in infile:
count=count+1
total=count
print "Total number of lines: ",total
infile.seek(0)
count=0
for line in infile:
edge=tuple(map(int,line.strip().split(",")))
edges.append(edge)
count=count+1
# for every million lines print memory consumption
if count%1000000==0:
print "Position: ", edge
print "Read ",float(count)/float(total)*100,"%."
mem=sys.getsizeof(edges)
for edge in edges:
mem=mem+sys.getsizeof(edge)
for node in edge:
mem=mem+sys.getsizeof(node)
print "Memory (Bytes): ", mem
La sortie je suis arrivé était:
Total number of lines: 30609720
Position: (9745, 2994)
Read 3.26693612356 %.
Memory (Bytes): 64348736
Position: (38857, 103574)
Read 6.53387224712 %.
Memory (Bytes): 128816320
Position: (83609, 63498)
Read 9.80080837067 %.
Memory (Bytes): 192553000
Position: (139692, 1078610)
Read 13.0677444942 %.
Memory (Bytes): 257873392
Position: (205067, 153705)
Read 16.3346806178 %.
Memory (Bytes): 320107588
Position: (283371, 253064)
Read 19.6016167413 %.
Memory (Bytes): 385448716
Position: (354601, 377328)
Read 22.8685528649 %.
Memory (Bytes): 448629828
Position: (441109, 3024112)
Read 26.1354889885 %.
Memory (Bytes): 512208580
Déjà après avoir lu seulement 25% du fichier 500MB, Python consomme 500 Mo. Il semble donc que stocker le contenu du fichier sous la forme d'une liste de tuples d'ints n'est pas très efficace en termes de mémoire. Y at-il une meilleure façon de le faire, de sorte que je peux lire dans mon fichier de 500 Mo dans mon 1 Go de mémoire?
Je suppose avec l'interprète, comme Python, u ne peut pas vraiment savoir où est la mémoire va. Cependant, les listes [habituellement - je ne connais pas l'implémentation exacte de Python) requièrent plus de mémoire que de tableaux, par exemple pour les pointeurs prev/next. Vous aurez probablement besoin d'utiliser C/C++ pour connaître exactement la quantité de mémoire que vous utilisez. – Drakosha
vous basez votre estimation de la mémoire sur les données brutes, mais ensuite créez des tuples et des ints. Comparé aux chaînes courtes, le surdébit d'instance de Python est visible ici comme vous pouvez le voir. Vous pouvez trier ces données même comme des chaînes pures, avez-vous essayé cela? – u0b34a0f6ae
Mon estimation de la mémoire ajoute la consommation de mémoire des ints, des tuples et de la liste. C'est plutôt correct, c'est à peu près le même (moins la mémoire consommée par l'interpréteur Python) que ce que je vois en utilisant top. Mais je n'ai pas essayé de trier les données comme des chaînes pures. Comment ferais-je cela? – asmaier