4 votes

Comment lire un fichier texte d'une ligne de 100 Go en Python ?

Je suis sur une plateforme Windows et j'utilise Python 3. Comme le comportement par défaut des lecteurs de fichiers est de consommer le fichier ligne par ligne, j'ai des difficultés à traiter mon fichier texte de 100 Go qui ne comporte qu'une seule ligne.

Je connais des solutions telles que este pour introduire un séparateur d'enregistrement personnalisé pour remplacer un caractère fréquent par \n mais je me demande s'il est possible de consommer et de traiter mon fichier uniquement via Python ?

Je n'ai que 8 Go de mémoire vive. Mon fichier est constitué des enregistrements des ventes (comprenant l'article, le prix, l'acheteur, ...). Mon traitement du fichier consiste principalement à modifier les numéros de prix. Les enregistrements sont séparés les uns des autres en utilisant | caractère.

5voto

kgr Points 579
# !/usr/bin/python3
import os, sys

# Open a file
fd = os.open("foo.txt",os.O_RDWR)

# Reading text
ret = os.read(fd,12)
print (ret.decode())

# Close opened file
os.close(fd)
print ("Closed the file successfully!!")

ou

with open(filename, 'rb') as f:
    while True:
        buf = f.read(max_size)
        if not buf:
            break
        process(buf)

ou

from functools import partial

with open('somefile', 'rb') as openfileobject:
    for chunk in iter(partial(openfileobject.read, 1024), b''):
        do_something()

2voto

Sam Mason Points 1389

Si vous utilisez un système d'exploitation 64 bits, vous pourriez mmap le fichier entier et laissez votre système d'exploitation faire la lecture en arrière-plan pour vous. mmap ed présentent la plupart du temps la même interface qu'un bytearray donc vous pouvez faire des choses comme :

import mmap

with open('largefile.txt', 'rb') as fd:
    buf = mmap.mmap(fd.fileno(), 0, access=mmap.ACCESS_READ)

vous pourrez alors utiliser buf comme une normale bytearray avec des opérations comme celle-ci pour itérer sur votre séparateur :

def split_sep(buf, sep=b'|'):
  pos = 0
  while True:
    end = buf.find(sep, pos)
    if end == -1:
       break
    yield buf[pos:end]
    pos = end + 1
  yield buf[pos:]

mais ce n'est qu'une démo. Vous voudrez probablement faire quelque chose de plus compliqué, peut-être décoder à partir d'octets avant de yield etc.

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