Python: Undo un'operazione di file readline () in modo del file-pointer è di nuovo in stato originale
Domanda
Sono la navigazione attraverso un puntatore a file Python di un file di testo in modalità di sola lettura utilizzando file.readline () alla ricerca di una linea speciale. Una volta che trovo che la linea voglio passare il puntatore del file a un metodo che si aspetta il puntatore del file per essere al via di quella readline (non subito dopo.)
Come faccio essenzialmente ad annullare una file.readline () operazione su un puntatore a file?
Soluzione
Si deve ricordare la posizione chiamando file.tell()
prima della readline e quindi chiamando file.seek()
per riavvolgere. Qualcosa di simile:
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()
Non riesco a ricordare se è sicuro di chiamare file.seek()
all'interno di un ciclo for line in file
così io di solito solo scrivere il ciclo while
. C'è probabilmente un modo molto più divinatorio di fare questo.
Altri suggerimenti
registrare il punto di partenza della linea con thefile.tell()
prima di chiamare readline
, e tornare a quel punto, se è necessario, 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'
>>>
, come si vede, il Seek / Tell "coppia" è "disfare", per così dire, il movimento del puntatore del file eseguito da readline
. Naturalmente, questo può solo lavorare su un file effettivo posizionabili (cioè, disco), non (ad esempio) il file come oggetti costruiti w / il metodo makefile di prese, ecc ecc.
Se il metodo vuole semplicemente per scorrere il file, allora si potrebbe utilizzare itertools.chain
per fare un iteratore appropriata:
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
Se non si conosce l'ultima riga perché non hai visita che si può leggere a ritroso fino a vedere un carattere nuova riga:
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