Reading Until EOF

Discussion in 'Python' started by Scott Brady Drummonds, Oct 21, 2003.

  1. Hi, everyone,

    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'?

    Thanks!
    Scott

    --
    Remove ".nospam" from the user ID in my e-mail to reply via e-mail.
     
    Scott Brady Drummonds, Oct 21, 2003
    #1
    1. Advertising

  2. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    At 2003-10-21T18:27:57Z, "Scott Brady Drummonds" <> writes:

    > 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:


    But it *is* exceptional behavior for the file read to fail. The normal
    behavior is for the call to succeed, right?

    Exceptions are handy for all sorts of things. One of my projects uses
    something like:

    class Success(Exception):
    def __init__(self, added = 0, deleted = 0, modified = 0):
    self.added = added
    self.deleted = deleted
    self.modified = modified

    to hold return values from various calls. I use it like:

    try:
    SomeDatabaseQuery()
    except Success, result:
    print 'Just added %d new entries.' % result.added
    except:
    print 'The query failed.'

    Don't limit yourself to a particular style simply because of the name.
    - --
    Kirk Strauser
    The Strauser Group
    Open. Solutions. Simple.
    http://www.strausergroup.com/
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.3 (GNU/Linux)

    iD8DBQE/lYgS5sRg+Y0CpvERAm9uAKCQsxlz2U7OgR/WI3FLSJKmACO0mwCePe9H
    d9mWtYpgEYOoDe7XvYjBm4E=
    =2ZUb
    -----END PGP SIGNATURE-----
     
    Kirk Strauser, Oct 21, 2003
    #2
    1. Advertising

  3. > > Per my experience with C++, [end of file] does not qualify
    > > as "exceptional behavior". Frankly, it is [expected]. I'd
    > > like to save the exceptions for true exceptions.


    > But it *is* exceptional behavior for the file read to fail. The
    > normal behavior is for the call to succeed, right?


    In C++, it would be considered bad style to use an exception to handle EOF.
    The idea is that reaching EOF is something that you *expect* to happen, even
    if only once. Similarly, the StopIteration exception would seem very odd to
    a C++ programmer, since you expect to reach the end of an iteration
    eventually.

    You might use a C++ exception to handle something like a disk read
    error--something that you do not expect to happen in the normal course of
    events.

    I realize the philosophy in Python is different--just trying to help clarify
    why the OP is troubled by Python's more liberal use of exceptions. Anyone
    coming from a C++ background is likely to have the same reaction at first.

    -Mike
     
    Michael Geary, Oct 21, 2003
    #3
  4. Scott Brady Drummonds wrote:
    ...
    > # 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


    It's a bad idea, as others have pointed out, but, sure -- as long as you
    change this into something like:
    while True:
    object = Object(file)
    if object is None: break
    self.list.append(object)
    or -- perhaps a bit more Pythonically, but otherwise equivalently:
    def Objfromfile(): return Object(file)
    self.list.extend([ object for object in iter(Objfromfile, None) ])

    > "empty" operator in Python that I could overload? Can I have a
    > constructor return 'null'?


    I'm not sure what an "empty operator" would be. You can easily
    make a function return None; use a factory function instead of the
    bare ctor and you're all set (you'd do it that way in C++ too, and
    there you'd have no alternative to that OR an exception).

    You _CAN_ have Object.__new__ return what you want -- iff it
    returns an instance of Object, that is then passed to Object.__init__.

    Basically calling Object(xxx) is like calling a function that does:
    def equivalent(xxx):
    result = Object.__new__(Object, xxx)
    if isinstance(result, Object): Object.__init__(result, xxx)
    return result
    but basically, for that to be used the way you want you need to do
    almost all the work in Object.__new__ rather than in __init__ --
    you can afford to let the latter be called only when you're fully
    satisfied you'll be able to construct an Object instance just fine.

    It IS a bad idea, but, if you insist, assuming that Object just
    needs a field of exactly 4 bytes it reads from the file, period;
    where you now have
    def __init__(self, file):
    self.field = file.read(4)
    if len(self.field) != 4: raise EOFError
    have no __init__ at all and instead a __new__:
    def __new__(cls, file):
    result = object.__new__(cls)
    result.field = file.read(4)
    if len(self.field) != 4: return None
    return result

    Using such exoteric techniques to avoid normal idiomatic usage
    and surprise every Python-aware reader of your code IS a bad
    idea. Be prepared to defend it craftily at the first code review!-)


    Alex
     
    Alex Martelli, Oct 21, 2003
    #4
  5. Scott Brady Drummonds

    Rainer Deyke Guest

    Scott Brady Drummonds wrote:
    > 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.


    That's a common, but to my mind very strange preference. If you handle an
    exception, the exception is by definition expected and "normal". Exceptions
    are just a way to exit from nested loops and function calls; there is
    nothing "exceptional" about them.


    --
    Rainer Deyke - - http://eldwood.com
     
    Rainer Deyke, Oct 21, 2003
    #5
  6. Scott Brady Drummonds

    Peter Otten Guest

    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
     
    Peter Otten, Oct 21, 2003
    #6
  7. Scott Brady Drummonds

    Ben Finney Guest

    On Tue, 21 Oct 2003 20:10:08 GMT, Kirk Strauser wrote:
    > But it *is* exceptional behavior for the file read to fail. The
    > normal behavior is for the call to succeed, right?


    No, it is a normal result for the call to succeed, and it is a normal
    result for end of file to be reached. The existence of one normal
    result does not make all others exceptional.

    --
    \ "I think it would be a good idea." -- Mahatma Gandhi (when |
    `\ asked what he thought of Western civilization) |
    _o__) |
    Ben Finney <http://bignose.squidly.org/>
     
    Ben Finney, Oct 22, 2003
    #7
  8. Scott Brady Drummonds

    Donn Cave Guest

    Quoth Kirk Strauser <>:
    | At 2003-10-21T18:27:57Z, "Scott Brady Drummonds" <scott.b.drummonds.nospam@=
    | intel.com> writes:
    |
    |> 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:
    |
    | But it *is* exceptional behavior for the file read to fail. The normal
    | behavior is for the call to succeed, right?

    Indeed, let me be the 7th or so person to chime in here. To be
    precise, I think rather than `normal' and `succeed', I would just
    say that the function has a meaning like `next line from file'.
    Functions with such simple meanings can exist because of exceptions -
    we decide what the function means, and we make it truly mean that by
    raising an exception otherwise.

    | Exceptions are handy for all sorts of things. One of my projects uses
    | something like:
    |
    | class Success(Exception):
    | def __init__(self, added = 0, deleted = 0, modified = 0):
    | self.added = added
    | self.deleted = deleted
    | self.modified = modified
    |
    | to hold return values from various calls. I use it like:
    |
    | try:
    | SomeDatabaseQuery()
    | except Success, result:
    | print 'Just added %d new entries.' % result.added
    | except:
    | print 'The query failed.'

    Hm, it isn't so clear why this is a good idea.

    Donn Cave,
     
    Donn Cave, Oct 22, 2003
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ian Bicking

    Re: Reading Until EOF

    Ian Bicking, Oct 21, 2003, in forum: Python
    Replies:
    0
    Views:
    514
    Ian Bicking
    Oct 21, 2003
  2. Kobu
    Replies:
    10
    Views:
    657
    Keith Thompson
    Mar 4, 2005
  3. SpreadTooThin

    ifstream eof not reporting eof?

    SpreadTooThin, Jun 13, 2007, in forum: C++
    Replies:
    10
    Views:
    713
    James Kanze
    Jun 15, 2007
  4. korean_dave

    readln() until EOF

    korean_dave, Jul 24, 2008, in forum: Python
    Replies:
    1
    Views:
    418
    Bruno Desthuilliers
    Jul 24, 2008
  5. Jan Burse
    Replies:
    67
    Views:
    1,109
    Jan Burse
    Mar 14, 2012
Loading...

Share This Page