Voici une réponse semblable à celle de MizardX, mais sans le problème apparent de prendre un temps quadratique dans le pire des cas à cause de la recherche répétée de nouvelles lignes dans la chaîne de travail au fur et à mesure que des morceaux sont ajoutés.
Par rapport à la solution Active State (qui semble également quadratique), cette solution n'explose pas dans le cas d'un fichier vide et effectue une recherche par bloc lu au lieu de deux.
Par rapport à la "queue" de frai, il s'agit d'un phénomène autonome. (Mais "tail" est préférable si vous l'avez déjà).
Par rapport à la prise de quelques kB à la fin et à l'espoir que cela suffise, cette méthode fonctionne pour n'importe quelle longueur de ligne.
import os
def reversed_lines(file):
"Generate the lines of file in reverse order."
part = ''
for block in reversed_blocks(file):
for c in reversed(block):
if c == '\n' and part:
yield part[::-1]
part = ''
part += c
if part: yield part[::-1]
def reversed_blocks(file, blocksize=4096):
"Generate blocks of file's contents in reverse order."
file.seek(0, os.SEEK_END)
here = file.tell()
while 0 < here:
delta = min(blocksize, here)
here -= delta
file.seek(here, os.SEEK_SET)
yield file.read(delta)
L'utiliser comme demandé :
from itertools import islice
def check_last_10_lines(file, key):
for line in islice(reversed_lines(file), 10):
if line.rstrip('\n') == key:
print 'FOUND'
break
Edita: remplacement de map() par itertools.imap() dans head(). Editer 2 : simplifié reversed_blocks(). Editer 3 : éviter d'analyser à nouveau la queue pour les nouvelles lignes. Editer 4 : a réécrit reversed_lines() parce que str.splitlines() ignore un ' final. \n comme l'a remarqué BrianB (merci).
Notez que dans les très anciennes versions de Python, la concaténation de chaînes de caractères dans une boucle prendra un temps quadratique. CPython depuis au moins quelques années évite ce problème automatiquement.
2 votes
Duplicata exact de stackoverflow.com/questions/136168/tail-a-file-with-python .