2010-07-21 21 views
10

Estoy escribiendo un programa que analizará un archivo de registro de Apache periódicamente para registrar sus visitantes, uso de ancho de banda, etc.Python: ¿cómo puedo abrir un archivo y especificar el desplazamiento en bytes?

El problema es que no quiero abrir el registro y analizar los datos que he ya analizado Por ejemplo:

line1 
line2 
line3 

Si analizo ese archivo, voy a guardar todas las líneas a continuación, salvo que compensan. De esa manera, cuando analizarlo de nuevo, me sale:

line1 
line2 
line3 - The log will open from this point 
line4 
line5 

segunda vez, voy a conseguir line4 y line5. Esperemos que esto tenga sentido ...

Lo que necesito saber es, ¿cómo puedo lograr esto? Python tiene la función seek() para especificar el desplazamiento ... ¿Acabo de obtener el tamaño de archivo del registro (en bytes) después de analizarlo y luego usarlo como el desplazamiento (en seek()) la segunda vez que lo registro?

Parece que no se me ocurre una manera de codificar esto>. <

Respuesta

13

puede administrar la posición en los archivos gracias a los seek y tell métodos de la clase file ver https://docs.python.org/2/tutorial/inputoutput.html

El método tell le dirá dónde buscar la próxima vez que abra

+0

Parece que hará exactamente lo que yo quiero. Aclamaciones. – dave

+1

Hmm, parece que el enlace debe actualizarse. No tiene referencia a objetos de archivo; Quizás: https://docs.python.org/2/tutorial/inputoutput.html – cevaris

1

Si sus archivos de registro se adaptan con facilidad en la memoria (esto es, usted tiene una política de rotación razonable) que puede hacer fácilmente algo como:

log_lines = open('logfile','r').readlines() 
last_line = get_last_lineprocessed() #From some persistent storage 
last_line = parse_log(log_lines[last_line:]) 
store_last_lineprocessed(last_line) 

Si no puede hacer esto, usted puede usar algo como (véase el uso de respuesta aceptada de buscar y contar, en caso de tener que hacerlo con ellos) Get last n lines of a file with Python, similar to tail

+0

Los registros son para hosts virtuales, por lo que actualmente no hay rotación de registros. Supongo que debería investigar cómo configurar eso ... lo que haría que tu solución sea bastante útil. Aclamaciones. – dave

0

Si va a analizar su línea de registro por línea, usted podría ahorrar Juste número de línea desde el último análisis. Tendría entonces que comenzar a leerlo desde la buena línea la próxima vez.

Buscar es más útil cuando tiene que estar en un lugar muy específico del archivo.

0

fácil pero no es recomendable :):

last_line_processed = get_last_line_processed()  
with open('file.log') as log 
    for record_number, record in enumerate(log): 
     if record_number >= last_line_processed: 
      parse_log(record) 
4
log = open('myfile.log') 
pos = open('pos.dat','w') 
print log.readline() 
pos.write(str(f.tell()) 
log.close() 
pos.close() 

log = open('myfile.log') 
pos = open('pos.dat') 
log.seek(int(pos.readline())) 
print log.readline() 

Por supuesto que no se debe utilizar como que - usted debe envolver las operaciones en funciones como save_position(myfile) y load_position(myfile), pero la funcionalidad es todo ahí.

0

Tenga en cuenta que se puede buscar() en Python desde el final del archivo:

f.seek(-3, os.SEEK_END) 

pone la posición de lectura 3 líneas de la EOF.

Sin embargo, ¿por qué no utilizar diff, ya sea desde el shell o con difflib?

+3

Eso pondría la posición de lectura 3 caracteres del EOF, no 3 líneas. – Duncan

0

Aquí está demostrando código utilizando la sugerencia longitud de la suya y la methond Tell:

beginning="""line1 
line2 
line3""" 

end="""- The log will open from this point 
line4 
line5""" 

openfile= open('log.txt','w') 
openfile.write(beginning) 
endstarts=openfile.tell() 
openfile.close() 

open('log.txt','a').write(end) 
print open('log.txt').read() 

print("\nAgain:") 
end2 = open('log.txt','r') 
end2.seek(len(beginning)) 

print end2.read() ## wrong by two too little because of magic newlines in Windows 
end2.seek(endstarts) 

print "\nOk in Windows also" 
print end2.read() 
end2.close() 
0

He aquí un fragmento eficiente y segura de hacer que salvar el desplazamiento de lectura en un archivo parallell. Básicamente logtail en python.

with open(filename) as log_fd: 
    offset_filename = os.path.join(OFFSET_ROOT_DIR,filename) 
    if not os.path.exists(offset_filename): 
     os.makedirs(os.path.dirname(offset_filename)) 
     with open(offset_filename, 'w') as offset_fd: 
      offset_fd.write(str(0)) 
    with open(offset_filename, 'r+') as offset_fd: 
     log_fd.seek(int(offset_fd.readline()) or 0) 
     new_logrows_handler(log_fd.readlines()) 
     offset_fd.seek(0) 
     offset_fd.write(str(log_fd.tell())) 
Cuestiones relacionadas