Yet another way to read a file line by line, starting at the end.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #!/usr/bin/env python
# -*-mode: python; coding: iso-8859-1 -*-
#
# Copyright (c) Peter Astrand <astrand@cendio.se>
import os
import string
class BackwardsReader:
    """Read a file line by line, backwards"""
    BLKSIZE = 4096
    def readline(self):
        while 1:
            newline_pos = string.rfind(self.buf, "\n")
            pos = self.file.tell()
            if newline_pos != -1:
                # Found a newline
                line = self.buf[newline_pos+1:]
                self.buf = self.buf[:newline_pos]
                if pos != 0 or newline_pos != 0 or self.trailing_newline:
                    line += "\n"
                return line
            else:
                if pos == 0:
                    # Start-of-file
                    return ""
                else:
                    # Need to fill buffer
                    toread = min(self.BLKSIZE, pos)
                    self.file.seek(-toread, 1)
                    self.buf = self.file.read(toread) + self.buf
                    self.file.seek(-toread, 1)
                    if pos - toread == 0:
                        self.buf = "\n" + self.buf
    def __init__(self, file):
        self.file = file
        self.buf = ""
        self.file.seek(-1, 2)
        self.trailing_newline = 0
        lastchar = self.file.read(1)
        if lastchar == "\n":
            self.trailing_newline = 1
            self.file.seek(-1, 2)
# Example usage
br = BackwardsReader(open('bar'))
while 1:
    line = br.readline()
    if not line:
        break
    print repr(line)
 | 
I know there are several recipes already, but I didn't like them, so I wrote my own implementation.
    Tags: files
  
  

 Download
Download Copy to clipboard
Copy to clipboard
Simplifying code transformations. * Converted to a generator
Use string methods instead of string module
trailing_newline set with a single test
Nested if-statements collapsed to if/elif/else
Replace var!=0 comparison with simple boolean test
Import of os module was unused
def BackwardsReader(file, BLKSIZE = 4096): """Read a file line by line, backwards"""
Example usage
for line in BackwardsReader(open('brent.txt')): print repr(line)
Minor change to Hettinger's post to get around limitations with io.seek in Python v3.1 The above fails with:
IOError: can't do nonzero end-relative seeks at
5: file.seek(-1, 2)
and
IOError: can't do nonzero cur-relative seeks at 34: file.seek(-toread, 1) 36: file.seek(-toread, 1)
<code>
def reverseReadFile(file, BLKSIZE = 4096): """Read a file line by line, backwards""" buf = ""
</code>
Thank you Peter, Raymond and Kevin!