open.read

Alex Martelli aleaxit at yahoo.com
Thu Aug 21 08:38:38 EDT 2003


On Thursday 21 August 2003 01:49 pm, François Pinard wrote:
   ...
> In more recent versions of Python, the `open' built in function has been
> replaced by the `file' built in constructor, and `open' has been made an
> alias for `file', so the above may more adequately be written:
>
>     stuff = file("filename", "r").read()

Except that, since open is an alias (and NOT deprecated), it's exactly
equivalent (IMHO) which name you choose to use.  If open ever DOES
get deprecated (perhaps in 3.0, some years from now) that may change.


> The file object created by the `file' constructor has its own destructor,
> which closes the file automatically if not done already.  Using `file' is

In terms of the definition of the Python *language*, the "own destructor"
will run whenever it pleases; thus, it's CONCEIVABLE that (in some
perfectly valid and correct implementations of the Python language)
the file's closing is delayed all the way to the end of the program.  Keeping
files open needlessly is A Bad Thing, and if you're not closing them
explicitly you're relying on an IMPLEMENTATION detail (which may vary
between otherwise perfectly valid Python implementations) to save you
from that Bad Thing.  Don't.

> Pythonesque.  For simple usages like the one above, you can safely rely on
> Python for destroying the file object, even in extra-serious programs :-).
> "Better" is a question of opinion, but in the case here, it seems to me
> that cluttering your code with an assignment, only meant for an explicit
> close, does not buy you legibility, and moreover, your assignment will get
> your closed file object uselessly hanging around.  Best is exactly what you
> did. (I would have not used the `, "r"' part in this case.)

I agree that the explicit use of the default 'r' option is debatable (explicit 
is better than implicit, but one does not want extra clutter -- hard to 
call).  I emphatically disagree that relying on an implementation detail
to avoid uselessly hogging resources is 'best'!  If the few bytes taken by
a closed fileobject matter in your case -- that's what the del statement
is for.


> > it will make your code more usable in Jython,
>
> This is likely the only real advantage of cluttering your code, when you
> know or bet that you are going to use Jython one of these days.

Or PyPy, or some future implementation of Python for dotNET, or
perhaps some optimizer such as psyco if it uses the semantic freedom
the language definition so explicitly grants it to speed programs up by
delaying/bunching up destructor-calls -- or, really, *ANY* implementation
of the Python language save for those for whom you "KNOW" enough
about implementation details and particularities to rely on their "eager"
destructors-call semantics.

The distinction between a language and its several implementations
is very important.  A language defines an interface, via its specs; each
implementation that is correct implements that interface within the
degrees of freedom the language specs give it.

PROGRAM TO AN INTERFACE, NOT TO AN IMPLEMENTATION
is a wonderful, indeed crucial principle.

Relying on "extras" that specific implementations ensure above and
beyond what the INTERFACE'S specs guarantee is generally not
good programming style.  You get away with it in small and/or
"intended as throw-away" programs.  But it breeds bad habits that
may easily trip you when the time comes to write huge applications
that will last a long time and end up using other implementations of
the same language.

The idiom file('blah').read() == just like the perfectly identical one
open('blah').read() == relies on implementation details: using it is
a violation of the "program to an interface" principle.

Now try/finally IS slightly bothersome to use -- you have to put
the initialization BEFORE the try, not IN it, for example -- yet its
semantics are truly crucial.  This is the reason easier-to-use
syntax alternatives to try/finally are considered on Python-Dev --
encourage everybody to rely on GUARANTEED finalization rather
than implementation accidents that may work on some correct
implementations of the Python language but NOT on others.

But even now, though the syntactic enhancements are not there
yet and nobody can be sure if and how they'll eventuate, the
semantics of try/finally are just as important -- and, IMHO, in any
"real" program well worth the little bothers that try/finally gives.


Alex






More information about the Python-list mailing list