[Tutor] deriving class from file to handle input line numbers?

Duncan Gibson duncan at thermal.esa.int
Tue Aug 16 11:18:51 CEST 2005


I was sure that this must be a frequently asked [homework?] question,
but trying to search for 'file open line number' didn't throw up the
sort of answers I was looking for, so here goes...

I regularly write parsers for simple input files, and I need to give
helpful error messages if the input is invalid. The three most helpful
pieces on information are file name, line number and line content. Of
course I can use a global variable to track how many times f.readline()
is called, but I was wondering whether there is a more OO or Python
way of encapsulating this within a class derived from file.

What I have below is the minimal interface that I could come up with,
but it is a file adaptor rather than a derived class, and it doesn't
seem quite clean to me, because I have to open the file externally
and then pass the file object into the constructor.

Is there a better way of doing it, or am I chasing rainbows?

Cheers
Duncan

class LineCountedInputFile(object):
    """
    add input line count to minimal input File interface

    The file must be opened externally, and then passed into the
    constructor.  All access should occur through the readLine method,
    and not using normal File methods on the external file variable,
    otherwise things will get out of sync and strange things could
    happen, including incorrect line number.
    """
    
    __slots__ = (
            '_inputFile',
            '_lineNumber')
    
    def __init__(self, inputFile):
        """
        create a LineCountedInputFile adaptor object
        
        :param inputFile: existing File object already open for reading only
        :type  inputFile: `File`
        """
        
        assert isinstance(inputFile, file)
        assert not inputFile.closed and inputFile.mode == 'r'
        
        self._inputFile = inputFile
        self._lineNumber = 0

    #----------------------------------------------------------------------
        
    def readLine(self):
        """
        call file.readline(), strip excess whitespace, increment line number
        
        :return: next line of text from file minus excess whitespace, or
                None at end-of-file
        :rtype:  str
        """
        
        line = self._inputFile.readline()
        if len(line) == 0:
            return None
        self._lineNumber += 1
        return line.strip()

    #----------------------------------------------------------------------
    
    def _get_fileName(self):
        return self._inputFile.name
        
    fileName = property(_get_fileName, None, None, """(read-only)""")

    #----------------------------------------------------------------------
    
    def _get_lineNumber(self):
        return self._lineNumber
        
    lineNumber = property(_get_lineNumber, None, None, """(read-only)""")



More information about the Tutor mailing list