Python: Undo eine Datei Readline- () -Operation so Datei-Pointer ist wieder im ursprünglichen Zustand
Frage
Ich bin gerade durch einen Python-Datei Zeiger einer Textdatei im Nur-Lese-Modus file.readline () auf der Suche nach einer speziellen Linie. Sobald ich diese Zeile finden möchte ich die Datei Zeiger auf eine Methode zu übergeben, die den Dateizeiger erwarten am Anfang dieser Readline- zu sein (nicht direkt nach dem Spiel.)
Wie im wesentlichen ich rückgängig macht einen file.readline () Operation auf einem Dateizeiger?
Lösung
Sie haben die Position erinnern file.tell()
vor dem Readline- aufrufen und dann file.seek()
zurückzuspulen aufrufen. So etwas wie:
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()
Ich kann mich nicht erinnern, ob es sicher ist file.seek()
innerhalb eines for line in file
Schleife zu nennen, damit ich in der Regel nur die while
Schleife auszuschreiben. Es ist wahrscheinlich eine viel pythonic Art und Weise, dies zu tun.
Andere Tipps
Sie den Startpunkt der Linie mit thefile.tell()
aufzuzeichnen, bevor Sie readline
rufen, und zu diesem Punkt zurück, wenn es nötig ist, mit 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'
>>>
Wie Sie sehen, die Seek / tell „Paar“ wird „rückgängig gemacht“, so zu sprechen, führte die Dateizeigerbewegung durch readline
. Natürlich kann dies nur die Arbeit an einer tatsächlichen seekable (das heißt, Disk-Datei), nicht (z) auf dateiähnliche Objekten w / Makefile-Methode von Steckdosen eingebaut, etc etc.
Wenn Ihre Methode einfach zu wiederholen durch die Datei will, dann könnte man itertools.chain
verwenden, um eine geeignete Iterator zu machen:
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
Wenn Sie nicht die letzte Zeile wissen, weil Sie es nicht besuchen Sie können rückwärts gelesen, bis ein Newline-Zeichen zu sehen:
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