335 votes

Comment puis-je lire des fichiers texte volumineux en Python, ligne par ligne, sans les charger en mémoire ?

J'ai besoin de lire un gros fichier, ligne par ligne. Disons que ce fichier a plus de 5 Go et que j'ai besoin de lire chaque ligne, mais je ne veux évidemment pas utiliser la fonction readlines() car cela va créer une très grande liste dans la mémoire.

Comment le code ci-dessous fonctionnera-t-il dans ce cas ? Est-ce que xreadlines lui-même en lisant un par un dans la mémoire ? L'expression du générateur est-elle nécessaire ?

f = (line for line in open("log.txt").xreadlines())  # how much is loaded in memory?

f.next()  

De plus, que puis-je faire pour lire ceci dans l'ordre inverse, comme le Linux tail commande ?

J'ai trouvé :

http://code.google.com/p/pytailer/

y

" python head, tail et backward lire par lignes d'un fichier texte "

Les deux ont très bien fonctionné !

0 votes

Et que puis-je faire pour lire cela depuis la queue ? ligne par ligne, en commençant par la dernière ligne.

0 votes

Ceci devrait être une question séparée

1 votes

0voto

Arohi Gupta Points 22

Que pensez-vous de cela ? Divisez votre fichier en morceaux et lisez-le ligne par ligne, car lorsque vous lisez un fichier, votre système d'exploitation met en cache la ligne suivante. Si vous lisez le fichier ligne par ligne, vous n'utilisez pas efficacement les informations mises en cache.

Au lieu de cela, divisez le fichier en morceaux et chargez le morceau entier en mémoire, puis effectuez votre traitement.

def chunks(file,size=1024):
    while 1:

        startat=fh.tell()
        print startat #file's object current position from the start
        fh.seek(size,1) #offset from current postion -->1
        data=fh.readline()
        yield startat,fh.tell()-startat #doesnt store whole list in memory
        if not data:
            break
if os.path.isfile(fname):
    try:
        fh=open(fname,'rb') 
    except IOError as e: #file --> permission denied
        print "I/O error({0}): {1}".format(e.errno, e.strerror)
    except Exception as e1: #handle other exceptions such as attribute errors
        print "Unexpected error: {0}".format(e1)
    for ele in chunks(fh):
        fh.seek(ele[0])#startat
        data=fh.read(ele[1])#endat
        print data

0voto

John Haynes Points 1

Merci ! Je suis récemment passé à python 3 et j'étais frustré par l'utilisation de readlines(0) pour lire de gros fichiers. Ceci a résolu le problème. Mais pour obtenir chaque ligne, j'ai dû faire quelques étapes supplémentaires. Chaque ligne était précédée d'un 'b', ce qui signifie qu'elle était au format binaire. L'utilisation de "decode(utf-8)" l'a transformé en ascii.

Ensuite, j'ai dû enlever un "=". \n "au milieu de chaque ligne.

Puis je divise les lignes à la nouvelle ligne.

b_data=(fh.read(ele[1]))#endat This is one chunk of ascii data in binary format
        a_data=((binascii.b2a_qp(b_data)).decode('utf-8')) #Data chunk in 'split' ascii format
        data_chunk = (a_data.replace('=\n','').strip()) #Splitting characters removed
        data_list = data_chunk.split('\n')  #List containing lines in chunk
        #print(data_list,'\n')
        #time.sleep(1)
        for j in range(len(data_list)): #iterate through data_list to get each item 
            i += 1
            line_of_data = data_list[j]
            print(line_of_data)

Voici le code qui commence juste au-dessus de "print data" dans le code d'Arohi.

0voto

Ali Sajjad Points 810

La meilleure solution que j'ai trouvée à ce sujet, et je l'ai essayée sur un fichier de 330 Mo.

lineno = 500
line_length = 8
with open('catfour.txt', 'r') as file:
    file.seek(lineno * (line_length + 2))
    print(file.readline(), end='')

Où longueur_ligne est le nombre de caractères d'une seule ligne. Par exemple, "abcd" a une longueur de ligne de 4.

J'ai ajouté 2 à la longueur de la ligne pour sauter le '. \n et passer au caractère suivant.

-1voto

Adam Points 182

Cela peut s'avérer utile lorsque vous souhaitez travailler en parallèle et ne lire que des morceaux de données tout en conservant de nouvelles lignes.

def readInChunks(fileObj, chunkSize=1024):
    while True:
        data = fileObj.read(chunkSize)
        if not data:
            break
        while data[-1:] != '\n':
            data+=fileObj.read(1)
        yield data

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X