python - limpiar - labels en tkinter
¿Cómo puedo alinear un archivo de registro en Python? (10)
Me gustaría que la salida de cola -F o algo similar esté disponible para mí en Python sin bloquear o bloquear. He encontrado un código muy viejo para hacer eso here , pero estoy pensando que debe haber una mejor manera o una biblioteca para hacer lo mismo por ahora. Alguien sabe de uno?
Idealmente, tendría algo como tail.getNewData()
que podría llamar cada vez que quisiera más datos.
Idealmente, tendría algo como tail.getNewData () que podría llamar cada vez que quisiera más datos
Ya tenemos uno y es muy agradable. Simplemente llame a f.read () cada vez que desee más datos. Comenzará a leer donde quedó la lectura anterior y leerá hasta el final de la secuencia de datos:
f = open(''somefile.log'')
p = 0
while True:
f.seek(p)
latest_data = f.read()
p = f.tell()
if latest_data:
print latest_data
print str(p).center(10).center(80, ''='')
Para leer línea por línea, use f.readline () . A veces, el archivo que se lee terminará con una línea parcialmente leída. Maneje ese caso con f.tell () buscando la posición actual del archivo y usando f.seek () para mover el puntero del archivo al principio de la línea incompleta. Vea esta receta de ActiveState para el código de trabajo.
Sin bloqueo
Si está en Linux (ya que Windows no admite la selección de llamadas en los archivos) puede usar el módulo de subproceso junto con el módulo de selección.
import time
import subprocess
import select
f = subprocess.Popen([''tail'',''-F'',filename],/
stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p = select.poll()
p.register(f.stdout)
while True:
if p.poll(1):
print f.stdout.readline()
time.sleep(1)
Este sondea la tubería de salida para nuevos datos y la imprime cuando está disponible. Normalmente el time.sleep(1)
y la print f.stdout.readline()
se reemplazarán por un código útil.
Bloqueo
Puede utilizar el módulo de subproceso sin las llamadas de módulo de selección adicionales.
import subprocess
f = subprocess.Popen([''tail'',''-F'',filename],/
stdout=subprocess.PIPE,stderr=subprocess.PIPE)
while True:
line = f.stdout.readline()
print line
Esto también imprimirá nuevas líneas a medida que se agreguen, pero se bloqueará hasta que se cierre el programa de cola, probablemente con f.kill()
.
Entonces, esto llega bastante tarde, pero me encontré con el mismo problema otra vez, y ahora hay una solución mucho mejor. Solo usa el pygtail :
Pygtail lee líneas de archivos de registro que no se han leído. Incluso manejará los archivos de registro que se han girado. Basado en Logcheck''s logtail2 ( http://logcheck.org )
La única forma portátil de tail -f
un archivo parece ser, de hecho, leer de ella y volver a intentar (después de un sleep
) si la read
devuelve 0. Las utilidades de tail
en varias plataformas usan trucos específicos de plataforma (por ejemplo, kqueue
en BSD ) para cola eficientemente un archivo para siempre sin necesidad de sleep
.
Por lo tanto, implementar una buena tail -f
puramente en Python probablemente no sea una buena idea, ya que tendrías que usar la implementación del mínimo denominador común (sin recurrir a hacks específicos de la plataforma). Usando un subprocess
simple para abrir tail -f
e iterar a través de las líneas en un subproceso separado, puede implementar fácilmente una operación de tail
no bloqueante en Python.
Ejemplo de implementación:
import threading, Queue, subprocess
tailq = Queue.Queue(maxsize=10) # buffer at most 100 lines
def tail_forever(fn):
p = subprocess.Popen(["tail", "-f", fn], stdout=subprocess.PIPE)
while 1:
line = p.stdout.readline()
tailq.put(line)
if not line:
break
threading.Thread(target=tail_forever, args=(fn,)).start()
print tailq.get() # blocks
print tailq.get_nowait() # throws Queue.Empty if there are no lines to read
Otra opción es la biblioteca de tailhead
que proporciona tanto las versiones de Python de tail
utilidades de tail
y head
como las API que se pueden usar en su propio módulo.
Originalmente basado en el módulo tailer
, su principal ventaja es la capacidad de seguir archivos por ruta, es decir, puede manejar la situación cuando se recrea el archivo. Además, tiene algunas correcciones de errores para varios casos de borde.
Puede usar la biblioteca ''tailer'': https://pypi.python.org/pypi/tailer/
Tiene una opción para obtener las últimas líneas:
# Get the last 3 lines of the file
tailer.tail(open(''test.txt''), 3)
# [''Line 9'', ''Line 10'', ''Line 11'']
Y también puede seguir un archivo:
# Follow the file as it grows
for line in tailer.follow(open(''test.txt'')):
print line
Si uno quiere un comportamiento parecido a la cola, esa parece ser una buena opción.
Python es "pilas incluidas", tiene una buena solución para ello: https://pypi.python.org/pypi/pygtail
Lee las líneas del archivo de registro que no se han leído. Recuerda dónde terminó la última vez, y continúa desde allí.
import sys
from pygtail import Pygtail
for line in Pygtail("some.log"):
sys.stdout.write(line)
Si está en Linux, implemente una implementación sin bloqueo en python de la siguiente manera.
import subprocess
subprocess.call(''xterm -title log -hold -e /"tail -f filename/"&'', shell=True, executable=''/bin/csh'')
print "Done"
También puede usar el comando ''AWK''.
Ver más en: http://www.unix.com/shell-programming-scripting/41734-how-print-specific-lines-awk.html
awk se puede usar para alinear la última línea, las últimas líneas o cualquier línea en un archivo.
Esto se puede llamar desde Python.
Usando el módulo sh (instalación pip sh):
from sh import tail
# runs forever
for line in tail("-f", "/var/log/some_log_file.log", _iter=True):
print(line)
[actualizar]
Como sh.tail con _iter
= True es un generador, puedes:
import sh
tail = sh.tail("-f", "/var/log/some_log_file.log", _iter=True)
Entonces puedes "obtener nuevos datos" con:
new_data = tail.next()
Tenga en cuenta que si el buffer de cola está vacío, bloqueará hasta que haya más datos (de su pregunta no está claro qué es lo que quiere hacer en este caso).
[actualizar]
Esto funciona si reemplazas -f con -F, pero en Python estaría bloqueando. Estaría más interesado en tener una función a la que pudiera llamar para obtener nuevos datos cuando quiera, si eso es posible. - Eli
Un generador de contenedores colocando la llamada de la cola dentro de un ciclo True y atrapando eventuales excepciones de E / S tendrán casi el mismo efecto de -F.
def tail_F(some_file):
while True:
try:
for line in sh.tail("-f", some_file, _iter=True):
yield line
except sh.ErrorReturnCode_1:
yield None
Si el archivo se vuelve inaccesible, el generador devolverá None. Sin embargo, todavía bloquea hasta que haya nuevos datos si se puede acceder al archivo. No está claro para mí lo que quieres hacer en este caso.
El enfoque de Raymond Hettinger parece bastante bueno:
def tail_F(some_file):
first_call = True
while True:
try:
with open(some_file) as input:
if first_call:
input.seek(0, 2)
first_call = False
latest_data = input.read()
while True:
if ''/n'' not in latest_data:
latest_data += input.read()
if ''/n'' not in latest_data:
yield ''''
if not os.path.isfile(some_file):
break
continue
latest_lines = latest_data.split(''/n'')
if latest_data[-1] != ''/n'':
latest_data = latest_lines[-1]
else:
latest_data = input.read()
for line in latest_lines[:-1]:
yield line + ''/n''
except IOError:
yield ''''
Este generador devolverá '''' si el archivo se vuelve inaccesible o si no hay nuevos datos.
[actualizar]
La penúltima respuesta gira alrededor de la parte superior del archivo cuando parece que se queda sin datos. - Eli
Creo que el segundo dará salida a las últimas diez líneas cada vez que finalice el proceso de cola, que con -f
es siempre que hay un error de E / S. El comportamiento de tail --follow --retry
no está lejos de esto en la mayoría de los casos que se me ocurre en entornos de tipo Unix.
Quizás si actualizas tu pregunta para explicar cuál es tu objetivo real (la razón por la que quieres imitar la cola), obtendrás una mejor respuesta.
La última respuesta en realidad no sigue la cola y simplemente lee lo que está disponible en tiempo de ejecución. - Eli
Por supuesto, cola mostrará las últimas 10 líneas por defecto ... Puede colocar el puntero del archivo al final del archivo usando file.seek, dejaré una implementación adecuada como ejercicio para el lector.
En mi humilde opinión, el enfoque file.read () es mucho más elegante que una solución basada en subprocesos.