import collections,cStringIO def rev_readlines(arg): f=open(arg,'rb') f.seek(0,2)# go to the end line=collections.deque() while f.tell(): f.seek(-1,1) c=f.read(1) f.seek(-1,1) line.appendleft(c) if c =='\n': yield ''.join(line).strip() line.clear() #clear for next line yield ''.join(line).strip() #bit of optimization, load groups of bytes from disk into memory def rev_readlines2(arg,bufsize=8192): f1=open(arg,'rb') f1.seek(0,2)# go to the end leftover='' while f1.tell(): print f1.tell() if f1.tell()<bufsize: bufsize=f1.tell() f1.seek(-bufsize,1) in_memory=f1.read(bufsize)+leftover f1.seek(-bufsize,1) buffer=cStringIO.StringIO(in_memory) buffer.seek(0,2)# go to the end line=collections.deque() while buffer.tell(): buffer.seek(-1,1) c=buffer.read(1) buffer.seek(-1,1) line.appendleft(c) if c =='\n': yield ''.join(line).strip() line.clear() leftover=''.join(line).strip() yield leftover #different approach and much faster def rev_readlines3(arg,bufsize=8192): f1=open(arg,'rb') f1.seek(0,2)# go to the end leftover='' while f1.tell(): if f1.tell()<bufsize: bufsize=f1.tell() f1.seek(-bufsize,1) in_memory=f1.read(bufsize)+leftover f1.seek(-bufsize,1) lines=in_memory.split('\n') for i in reversed(lines[1:]): yield i leftover=lines[0] yield leftover for i in rev_readlines(filename): print i