On Tue, 22 Mar 2005 19:51:28 -0800, Mike Rovner <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list