feof status (was: Re: [Python-Dev] Rehabilitating fgets)

Guido van Rossum guido@python.org
Sun, 07 Jan 2001 16:13:01 -0500

> Tim Peters <tim.one@home.com>:
> > I agree an .eof() method would be better than a data member.  Note that
> > whenever Python internals hit stream EOF today, they call clearerr(), so
> > simply adding an feof() wrapper wouldn't suffice.  Guido seemed to try to
> > make sure that feof() would never be useful <0.8 wink>.
> That's inconvenient, but only means the internal Python state flag
> that feof() would inspect would have to be checked after each read.

This was done because some platforms set feof() when there's still a
possibity to read more (e.g. after an interactive user typed ^D),
while others don't.  It's inconvenient to get an endless stream of
EOFs from stdin when a user typed ^D to one particular prompt, so I
decided to clear the EOF status.

[ESR in a later message]
> I considered trying a zero-length read() in Python, but this strikes me 
> as inelegant even if it would work.

I doubt that a zero-length read conveys any information.  It should
return "" whether or not there is more to read!  Plus, look at the
implementation of readline() (file_readline() in
Objects/fileobject.c): it shortcuts the n == 0 case and returns an
empty string without touching the file.

> > Before adding an eof() method, can you explain what your program is
> > trying to do?  Is it reading from a pipe or socket?  Then select() or
> > poll() might be useful.

[ESR again]
> Sadly, it's exactly the wrong case.  Hmmm...omitting irrelevant details,
> it's a situation where a markup file can contain sections in two different
> languages.  The design requires the first interpreter to exit on seeing
> either EOF or a marker that says "switching to second language".  For
> reasons too compllicated to explain, it would be best if the parser for
> the first language didn't simply call the second parser.
> The logic I wanted to write amounts to:
> while 1:
>     line = fp.readline()
>     if not line or line == "history":
>         break
>     interpret_in-language_1(line)
> if not fp.feof()
>     while 1:
>         line = fp.readline()
>         if not line:
>             break
>     	interpret_in-language_2(line)
> I just tested the zero-length-read method.  That worked.  I guess I'll
> use it.

Bizarre (given what I know about zero-length read).  But in the above
code, you can replace "if not fp.feof()" with "if line".  In other
words, you just have to carry the state over within your program.

So, I see no reason why the logic in your program couldn't take care
of this, which in general is a preferred way to solve a problem than
to change the language.

Also note that in Python it's no sin to attempt to read a line even
when the file is already at EOF -- you will simply get an empty line

--Guido van Rossum (home page: http://www.python.org/~guido/)