Read from the last line of a file?
Bengt Richter
bokr at oz.net
Wed Mar 23 20:44:19 EST 2005
On Tue, 22 Mar 2005 19:51:28 -0800, Mike Rovner <mrovner at propel.com> wrote:
>Anthony Liu wrote:
>> I am wondering if it is possible to start reading from
>> the last line of file, and then the last but one up to
>> the first line.
>
>If you can afford to keep the whole file in memory, than:
>
>lines = open(..).readlines()
>print lines[::-1]
>
>Otherwise you can use seek() to random-access file and read chunks,
>then extract lines from them and process them.
>See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/120686 for
>implementation details.
>
>Mike
>
Slightly different from cookbook, normalizing eols, also seeking to block boundary offsets
from start of file, which should be more os friendly. An alternative QND iterator over lines in reverse:
Just tested very slightly (I just came up with this minutes ago ;-), so don't depend on this without testing.
----< revfile.py >-------------------------------------
def revfile(path, bufsize=8192, linesep=__import__('os').linesep):
"""iterate through lines of a file in reverse"""
f = open(path, 'rb')
f.seek(0, 2) # to end
# keep to bufsize-multiple offsets
pos, tailsize = divmod(f.tell(), bufsize)
if tailsize==0:
pos = max(0, pos-1)
pos *= bufsize
f.seek(pos)
lines = f.read().split(linesep) # tail end buffer
# finesse eol on last line in case missing
if len(lines)>1 and lines[-1]=='':
endline = '\n'
lines.pop()
else:
endline = ''
while True:
if len(lines) == 1:
if pos == 0:
last = lines[0] + endline
if last: yield last # zero-length file has no lines
break
pos -= bufsize
assert pos>=0, 'should not fail'
f.seek(pos)
lines = (f.read(bufsize)+lines[0]).split(linesep)
else:
yield lines.pop() + endline
endline = '\n'
-------------------------------------------------------
Regards,
Bengt Richter
More information about the Python-list
mailing list