Existe-t-il des alternatives au code ci-dessous:
startFromLine = 141978 # or whatever line I need to jump to
urlsfile = open(filename, "rb", 0)
linesCounter = 1
for line in urlsfile:
if linesCounter > startFromLine:
DoSomethingWithThisLine(line)
linesCounter += 1
Si je traite un énorme fichier texte (~15MB)
avec des lignes de longueur inconnue mais différente, et que je dois passer à une ligne particulière, quel numéro je connais à l'avance? Je me sens mal en les traitant un par un alors que je sais que je pourrais ignorer au moins la première moitié du fichier. Vous recherchez une solution plus élégante s'il y en a.
python
text-files
user63503
la source
la source
Réponses:
linecache :
la source
Vous ne pouvez pas avancer sans lire le fichier au moins une fois, car vous ne savez pas où se trouvent les sauts de ligne. Vous pouvez faire quelque chose comme:
la source
Vous n'avez pas vraiment beaucoup d'options si les lignes sont de longueur différente ... vous devez malheureusement traiter les caractères de fin de ligne pour savoir quand vous êtes passé à la ligne suivante.
Cependant, vous pouvez accélérer considérablement cette opération ET réduire l'utilisation de la mémoire en modifiant le dernier paramètre sur «ouvrir» par quelque chose qui n'est pas 0.
0 signifie que l'opération de lecture de fichier est sans tampon, ce qui est très lent et gourmand en disque. 1 signifie que le fichier est mis en tampon en ligne, ce qui serait une amélioration. Tout ce qui est supérieur à 1 (disons 8k .. c'est-à-dire: 8096 ou plus) lit des morceaux du fichier en mémoire. Vous y accédez toujours via
for line in open(etc):
, mais python ne va que petit à petit, supprimant chaque morceau mis en mémoire tampon après son traitement.la source
Je suis probablement gâté par un bélier abondant, mais 15 M, ce n'est pas énorme. La lecture en mémoire avec
readlines()
est ce que je fais habituellement avec des fichiers de cette taille. Accéder à une ligne après cela est trivial.la source
Je suis surpris que personne ne soit mentionné islice
ou si vous voulez tout le reste du fichier
ou si vous voulez toutes les autres lignes du fichier
la source
Puisqu'il n'y a aucun moyen de déterminer la longueur de toutes les lignes sans les lire, vous n'avez pas d'autre choix que d'itérer sur toutes les lignes avant votre ligne de départ. Tout ce que vous pouvez faire est de lui donner une belle apparence. Si le fichier est vraiment énorme, vous pouvez utiliser une approche basée sur un générateur:
Remarque: l'indice est basé sur zéro dans cette approche.
la source
Si vous ne souhaitez pas lire l'intégralité du fichier en mémoire ... vous devrez peut-être trouver un format autre que le texte brut.
bien sûr, tout dépend de ce que vous essayez de faire et de la fréquence à laquelle vous sauterez dans le fichier.
Par exemple, si vous allez sauter plusieurs fois aux lignes dans le même fichier et que vous savez que le fichier ne change pas pendant que vous travaillez avec, vous pouvez faire ceci:
Commencez par parcourir le fichier entier et enregistrez le " find-location "de certains numéros de ligne-clé (comme, jamais 1000 lignes),
puis si vous voulez la ligne 12005, sautez à la position de 12000 (que vous avez enregistrée) puis lisez 5 lignes et vous saurez que vous êtes à la ligne 12005 et ainsi de suite
la source
Si vous connaissez à l'avance la position dans le fichier (plutôt que le numéro de ligne), vous pouvez utiliser file.seek () pour aller à cette position.
Edit : vous pouvez utiliser la fonction linecache.getline (filename, lineno) , qui retournera le contenu de la ligne lineno, mais seulement après avoir lu le fichier entier en mémoire. Bon si vous accédez au hasard à des lignes à partir du fichier (comme Python lui-même voudra peut-être le faire pour imprimer un retraçage) mais pas bon pour un fichier de 15 Mo.
la source
Qu'est-ce qui génère le fichier que vous souhaitez traiter? Si c'est quelque chose sous votre contrôle, vous pouvez générer un index (quelle ligne est à quelle position.) Au moment où le fichier est ajouté. Le fichier d'index peut être de taille de ligne fixe (espace avec espace ou 0 avec 0) et sera certainement plus petit. Et ainsi peut être lu et traité rapidement.
la source
J'ai eu le même problème (besoin de récupérer à partir d'une énorme ligne spécifique de fichier).
Sûrement, je peux à chaque fois parcourir tous les enregistrements du fichier et l'arrêter lorsque le compteur sera égal à la ligne cible, mais cela ne fonctionne pas efficacement dans un cas où vous souhaitez obtenir un nombre pluriel de lignes spécifiques. Cela a provoqué la résolution du problème principal - comment gérer directement à l'endroit nécessaire du fichier.
J'ai découvert la décision suivante: tout d'abord, j'ai terminé le dictionnaire avec la position de départ de chaque ligne (la clé est le numéro de ligne et la valeur - la longueur cumulée des lignes précédentes).
finalement, fonction de visée:
t.seek (line_number) - commande qui exécute l'élagage du fichier jusqu'à la création de la ligne. Donc, si vous validez ensuite readline, vous obtenez votre ligne cible.
En utilisant une telle approche, j'ai gagné beaucoup de temps.
la source
Vous pouvez utiliser mmap pour trouver le décalage des lignes. MMap semble être le moyen le plus rapide de traiter un fichier
exemple:
puis utilisez f.seek (décalages) pour passer à la ligne dont vous avez besoin
la source
Les lignes elles-mêmes contiennent-elles des informations d'index? Si le contenu de chaque ligne était quelque chose comme "
<line index>:Data
", alors l'seek()
approche pourrait être utilisée pour faire une recherche binaire dans le fichier, même si le montant deData
est variable. Vous cherchiez au milieu du fichier, lisez une ligne, vérifiez si son index est supérieur ou inférieur à celui que vous souhaitez, etc.Sinon, le mieux que vous puissiez faire est juste
readlines()
. Si vous ne voulez pas lire tous les 15 Mo, vous pouvez utiliser l'sizehint
argument pour au moins remplacer un grand nombre dereadline()
s par un plus petit nombre d'appels àreadlines()
.la source
Si vous avez affaire à un fichier texte et basé sur un système Linux , vous pouvez utiliser les commandes linux.
Pour moi, cela a bien fonctionné!
la source
Voici un exemple utilisant 'readlines (sizehint)' pour lire un morceau de lignes à la fois. DNS a souligné cette solution. J'ai écrit cet exemple parce que les autres exemples ici sont orientés sur une seule ligne.
la source
Aucune des réponses n'est particulièrement satisfaisante, voici donc un petit extrait pour vous aider.
Exemple d'utilisation:
Cela implique de faire beaucoup de recherches de fichiers, mais est utile dans les cas où vous ne pouvez pas mettre le fichier entier en mémoire. Il effectue une lecture initiale pour obtenir les emplacements des lignes (il lit donc tout le fichier, mais ne le garde pas en mémoire), puis chaque accès effectue une recherche de fichier après le fait.
J'offre l'extrait ci-dessus sous la licence MIT ou Apache à la discrétion de l'utilisateur.
la source
Peut utiliser cette fonction pour renvoyer la ligne n:
la source