Reading Until EOF

Peter Otten __peter__ at web.de
Tue Oct 21 18:37:25 EDT 2003


Scott Brady Drummonds wrote:

> I'm a Python novice and would love some tips on how I should perform the
> following task: I'd like to have my Python script read objects (using
> their
> constructors) and terminate gracefully when an EOF is encountered.  My
> first attempt looked like this:
> 
>   #  This is enclosed in a 'try' block
>   file = open(...)
>   while 1:
>     #  The Object constructor raises an exception for end-of-file
>     object = Object(file)
>     self.list = self.list + [object]
> 
> However, I'm not entirely comfortable having the Object constructor raise
> an
> exception when the end-of-file is hit.  Per my experience with C++, this
> does not qualify as "exceptional behavior".  Frankly, it is accepted.  I'd
> like to save the exceptions for true exceptions.  My next guess:
> 
>   #  This is enclosed in a 'try' block
>   file = open(...)
>   while object = Object(file):
>     self.list = self.list + [object]
> 
> With this implementation, the file reading stops both with an exception
> (raised by a parsing error, as an example) and when the Object constructor
> returns something that makes the while conditional fail.  However, therein
> lies the rub: I don't know how to do this in Python.
> 
> Is there a way for me to make the second implementation work?  Is there an
> "empty" operator in Python that I could overload?  Can I have a
> constructor return 'null'?

In Python constructors are precious, as there can only be one. I think it's
the wrong decision to let it construct an object from a file instance. I
would suggest a factory method instead:

class Object:
    def __init__(self, word):
        self.word = word
    def __str__(self):
        return self.word

def factory(instream):
    """ construct an Object from the first word of each nonwhite line
    """
    for line in instream:
        if line.strip():
            yield Object(line.split()[0].upper())

instream = file("fromfile.py")
try:
    alist = [o for o in factory(instream)]
finally:
    instream.close()

print "\n".join(map(str, alist))

The factory method could still explicitly raise an Exception for a more
complex file parsing algorithm (or simply return, if you stick with the
generator as shown above, but that is a StopIteration exception in
disguise), where you might want to separate the loop and the object
generation, but your client code is cleaner anyway.


Peter






More information about the Python-list mailing list