Python: Deshacer una operación de archivo readline () de modo puntero a fichero está de vuelta en su estado original

StackOverflow https://stackoverflow.com/questions/3505479

Pregunta

Estoy navegando a través de un puntero a un archivo Python de un archivo de texto en el modo de sólo lectura utilizando file.readline () en busca de una línea especial. Una vez que encuentro esa línea quiero pasar el puntero del archivo a un método que se espera que el puntero de archivo a estar en el inicio de ese readline (no justo después de ella.)

¿Cómo puedo deshacer esencialmente una file.readline () operación en un puntero a un archivo?

¿Fue útil?

Solución

Hay que recordar la posición llamando file.tell() antes de la readline y luego llamar a file.seek() rebobinado. Algo así como:

fp = open('myfile')
last_pos = fp.tell()
line = fp.readline()
while line != '':
  if line == 'SPECIAL':
    fp.seek(last_pos)
    other_function(fp)
    break
  last_pos = fp.tell()
  line = fp.readline()

No puedo recordar si es seguro para llamar dentro de un bucle file.seek() for line in file así que por lo general sólo escribir el bucle while. Probablemente hay una manera mucho más Pythonic de hacer esto.

Otros consejos

grabar el punto de partida de la línea con thefile.tell() antes de llamar readline, y volver a ese punto, si es necesario, con thefile.seek.

>>> with open('bah.txt', 'w') as f:
...   f.writelines('Hello %s\n' % i for i in range(5))
... 
>>> with open('bah.txt') as f:
...   f.readline()
...   x = f.tell()
...   f.readline()
...   f.seek(x)
...   f.readline()
... 
'Hello 0\n'
'Hello 1\n'
'Hello 1\n'
>>> 

Como se ve, la búsqueda / Tell "par" es "deshacer", por así decirlo, el movimiento del puntero del archivo realizado por readline. Por supuesto, esto sólo puede trabajar en un archivo real reubicable (es decir, el disco), no (por ejemplo) en archivo-como objetos construidos w / el método makefile de tomas de corriente, etc, etc.

Si su método simplemente quiere iterar a través del archivo, entonces se podría utilizar para hacer itertools.chain un iterador apropiado:

import itertools

def process(it):
    for line in it:
        print line,

with open(filename,'r') as f:
    for line in f:
        if 'marker' in line:
            it=itertools.chain((line,),f)
            process(it)
            break
fin = open('myfile')
for l in fin:
    if l == 'myspecialline':
        # Move the pointer back to the beginning of this line
        fin.seek(fin.tell() - len(l))
        break
# now fin points to the start of your special line

Si usted no sabe la última línea debido a que no lo visita se puede leer hacia atrás hasta que vea un carácter de nueva línea:

with open(logfile, 'r') as f:
    # go to EOF
    f.seek(0, os.SEEK_END)
    nlines = f.tell()
    i=0
    while True:
        f.seek(nlines-i)
        char = f.read(1)
        if char=='\n':
            break
        i+=1
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top