Pour écrire une fonction paresseuse, utilisez simplement yield
:
def read_in_chunks(file_object, chunk_size=1024):
"""Lazy function (generator) to read a file piece by piece.
Default chunk size: 1k."""
while True:
data = file_object.read(chunk_size)
if not data:
break
yield data
with open('really_big_file.dat') as f:
for piece in read_in_chunks(f):
process_data(piece)
Une autre option serait d'utiliser iter
et une fonction d'aide:
f = open('really_big_file.dat')
def read1k():
return f.read(1024)
for piece in iter(read1k, ''):
process_data(piece)
Si le fichier est basé sur des lignes, l'objet fichier est déjà un générateur de lignes paresseux:
for line in open('really_big_file.dat'):
process_data(line)
f = open('really_big_file.dat')
n'est donc qu'un pointeur sans aucune consommation de mémoire? (Je veux dire que la mémoire consommée est la même quelle que soit la taille du fichier?) Comment cela affectera-t-il les performances si j'utilise urllib.readline () au lieu de f.readline ()?rb
comme @Tal Weiss l'a mentionné; et manque unefile.close()
déclaration (pourrait utiliserwith open('really_big_file.dat', 'rb') as f:
pour accomplir la même chose; voir ici pour une autre mise en œuvre concise'rb'
n'est pas manquant.'b'
ses données très probablement corrompus . De la documentation -Python on Windows makes a distinction between text and binary files; [...] it’ll corrupt binary data like that in JPEG or EXE files. Be very careful to use binary mode when reading and writing such files.
Si votre ordinateur, votre système d'exploitation et python sont en 64 bits , vous pouvez utiliser le module mmap pour mapper le contenu du fichier en mémoire et y accéder avec des index et des tranches. Voici un exemple tiré de la documentation:
Si votre ordinateur, votre système d'exploitation ou python sont 32 bits , alors le mappage de gros fichiers peut réserver de grandes parties de votre espace d'adressage et affamer votre programme de mémoire.
la source
file.readlines()
prend un argument de taille facultative qui se rapproche du nombre de lignes lues dans les lignes retournées.la source
.read()
ne pas utiliser.readlines()
. Si le fichier est binaire, il ne comportera pas de sauts de ligne.Il existe déjà de nombreuses bonnes réponses, mais si tout votre fichier se trouve sur une seule ligne et que vous souhaitez toujours traiter les "lignes" (par opposition aux blocs de taille fixe), ces réponses ne vous seront d'aucune aide.
99% du temps, il est possible de traiter les fichiers ligne par ligne. Ensuite, comme suggéré dans cette réponse , vous pouvez utiliser l'objet fichier lui-même comme générateur paresseux:
Cependant, j'ai rencontré une fois un très gros fichier (presque) simple, où le séparateur de lignes n'était en fait pas
'\n'
mais'|'
.'|'
en'\n'
avant le traitement était également hors de question, car certains champs de ce csv contenaient'\n'
(saisie utilisateur en texte libre).Pour ce genre de situations, j'ai créé l'extrait de code suivant:
J'ai pu l'utiliser avec succès pour résoudre mon problème. Il a été largement testé, avec différentes tailles de morceaux.
Suite de tests, pour ceux qui veulent se convaincre.
la source
MISE À JOUR: L'approche est mieux expliquée dans https://stackoverflow.com/a/4566523/38592
la source
Reportez-vous à la documentation officielle de python https://docs.python.org/zh-cn/3/library/functions.html?#iter
Peut-être que cette méthode est plus pythonique:
la source
Je pense que nous pouvons écrire comme ceci:
la source
je ne suis pas autorisé à commenter en raison de ma faible réputation, mais la solution SilentGhosts devrait être beaucoup plus facile avec file.readlines ([sizehint])
méthodes de fichier python
edit: SilentGhost a raison, mais cela devrait être mieux que:
la source
Je suis dans une situation quelque peu similaire. Il n'est pas clair si vous connaissez la taille des morceaux en octets; Je ne le fais généralement pas, mais le nombre d'enregistrements (lignes) requis est connu:
Mise à jour : Merci nosklo. Voici ce que je voulais dire. Cela fonctionne presque, sauf qu'il perd une ligne «entre» des morceaux.
Est-ce que l'astuce sans perdre de lignes, mais ça n'a pas l'air très agréable.
la source
Pour traiter ligne par ligne, c'est une solution élégante:
Tant qu'il n'y a pas de lignes vides.
la source
open
qui vous donne déjà. Un fichier est déjà un itérateur sur ses lignes.vous pouvez utiliser le code suivant.
open () retourne un objet fichier
puis utilisez os.stat pour obtenir la taille
la source