python file tail

python - ¿Cómo implementar un equivalente pitónico de cola-F?



file tail (10)

Bueno, la forma más simple sería leer constantemente del archivo, verificar las novedades y probar los hits.

import time def watch(fn, words): fp = open(fn, ''r'') while True: new = fp.readline() # Once all lines are read this just returns '''' # until the file changes and a new line appears if new: for word in words: if word in new: yield (word, new) else: time.sleep(0.5) fn = ''test.py'' words = [''word''] for hit_word, hit_sentence in watch(fn, words): print "Found %r in line: %r" % (hit_word, hit_sentence)

Esta solución con readline funciona si sabes que tus datos aparecerán en líneas.

Si los datos son algún tipo de flujo, necesitas un buffer, más grande que la word más grande que estás buscando, y llenarlo primero. Se pone un poco más complicado de esa manera ...

¿Cuál es la forma pitónica de ver el final de un archivo en crecimiento para la aparición de ciertas palabras clave?

En shell, podría decir:

tail -f "$file" | grep "$string" | while read hit; do #stuff done


EDITAR: como indica el comentario a continuación, O_NONBLOCK no funciona para archivos en disco. Esto todavía ayudará si alguien más busca datos de la cola procedentes de un socket o tubería con nombre u otro proceso, pero no responde la pregunta real que se le hizo . La respuesta original permanece debajo para la posteridad. (Llamar a tail y grep funcionará, pero de todos modos no responde).

O_NONBLOCK el archivo con O_NONBLOCK y use select para buscar disponibilidad de lectura y luego read para leer los nuevos datos y los métodos de cadena para filtrar las líneas al final de un archivo ... o simplemente use el módulo de subprocess y deje que tail y grep hagan el trabajo para ti tal como lo harías en el caparazón.



Puede usar collections.deque para implementar tail.

Desde http://docs.python.org/library/collections.html#deque-recipes ...

def tail(filename, n=10): ''Return the last n lines of a file'' return deque(open(filename), n)

Por supuesto, esto lee el contenido completo del archivo, pero es una forma ordenada y concisa de implementar la cola.


Puede utilizar seleccionar para sondear los nuevos contenidos en un archivo.

def tail(filename, bufsize = 1024): fds = [ os.open(filename, os.O_RDONLY) ] while True: reads, _, _ = select.select(fds, [], []) if 0 < len(reads): yield os.read(reads[0], bufsize)


Que yo sepa, no hay equivalente a "cola" en la lista de funciones de Python. La solución sería usar tell () (obtener tamaño de archivo) y read () para calcular las líneas finales.

¡Esta publicación del blog (no por mí) tiene la función escrita, parece apropiada para mí! http://www.manugarg.com/2007/04/real-tailing-in-python.html


Si no puede restringir el problema de que funcione para una lectura basada en línea, necesita recurrir a bloques.

Esto debería funcionar:

import sys needle = "needle" blocks = [] inf = sys.stdin if len(sys.argv) == 2: inf = open(sys.argv[1]) while True: block = inf.read() blocks.append(block) if len(blocks) >= 2: data = "".join((blocks[-2], blocks[-1])) else: data = blocks[-1] # attention, this needs to be changed if you are interested # in *all* matches separately, not if there was any match ata all if needle in data: print "found" blocks = [] blocks[:-2] = [] if block == "": break

El desafío radica en garantizar que coincida con la aguja, incluso si está separada por dos límites de bloques.


Si solo necesitas una solución de Python 3 muerta y simple para procesar las líneas de un archivo de texto a medida que están escritas, y no necesitas el soporte de Windows, esto funcionó bien para mí:

import subprocess def tailf(filename): #returns lines from a file, starting from the beginning command = "tail -n +1 -F " + filename p = subprocess.Popen(command.split(), stdout=subprocess.PIPE, universal_newlines=True) for line in p.stdout: yield line for line in tailf("logfile"): #do stuff

Bloquea la espera de que se escriban nuevas líneas, por lo que no es adecuado para uso asincrónico sin algunas modificaciones.


puedes usar pytailf : envoltorio de cola de python simple

from tailf import tailf for line in tailf("myfile.log"): print line


def tail(f): f.seek(0, 2) while True: line = f.readline() if not line: time.sleep(0.1) continue yield line def process_matches(matchtext): while True: line = (yield) if matchtext in line: do_something_useful() # email alert, etc. list_of_matches = [''ERROR'', ''CRITICAL''] matches = [process_matches(string_match) for string_match in list_of_matches] for m in matches: # prime matches m.next() while True: auditlog = tail( open(log_file_to_monitor) ) for line in auditlog: for m in matches: m.send(line)

Yo uso esto para monitorear archivos de registro. En la implementación completa, guardo list_of_matches en un archivo de configuración para que pueda usarse con múltiples propósitos. En mi lista de mejoras es compatible con expresiones regulares en lugar de una simple coincidencia ''in''.