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