Q on explicitly calling file.close

David C. Ullrich dullrich at sprynet.com
Thu Sep 10 07:26:16 EDT 2009


On Wed, 9 Sep 2009 15:13:49 -0700 (PDT), r <rt8396 at gmail.com> wrote:

>On Sep 9, 4:19 pm, Charles Yeomans <char... at declareSub.com> wrote:
>(snip:)
>> Unfortunately, both of these simple templates have the following  
>> problem -- if open fails, a NameError will be raised from the finally  
>> block.
>
>(snip)
>> I removed the except block because I prefer exceptions to error codes.
>
>how will the caller know an exception has occurred? What if logic
>depends on the validation that a file *had* or *had not* been written
>too, huh?
>
>> In addition to fixing the latent bug in the second simple template, I  
>> took the opportunity to correct your heinous violation of command-
>> query separation.
>>
>> Charles Yeomans
>
>Oh I see! But what happens if the filename does not exist? What then?
>"open" will blow chucks thats what! Here is a version for our paranoid-
>schizophrenic-sadomasochist out there...

Well first, we agree that putting the open() in the try part of a
try-finally is wrong. try-finally is supposed to ensure that
_allocated_ resources are cleaned up.

What you do below may work. But it's essentially throwing
out exception handling and using error codes instead. There
are plenty of reasons why exceptions are preferred. The
standard thing is this:

def UseResource(rname):
  r = get(rname)
  try:
    r.use()
  finally
  r.cleanup()

Now if the get() fails, UseResource will indeed blow chunks.
That's what it _should_ do. Generally speaking, you should use
try-except very rarely, making certain you're catching the
exception at the appropriate level. Here for example in
_some_ uses of UseResource() you _want_ the application
to terminate if the get() fails. In that case you'd just call
UseResource() without any try-excpt. In some other
situation (maybe the user provided a filename that may
or may not exist) you want to trap the exception when
you _call_ UseResource():

try:
  UseResource(rname)
except WhateverError:
  print error message


>def egor_read_file(fname, mode='rb'):
>    print 'yes, master'
>    try:
>	f = open(fname, mode=mode)
>    except IOError:
>        return (0, 'But, the file no open master!')
>
>    try:
>        s = f.read()
>    except NameError:
>        return (0, 'the file still no open master!')
>
>    try:
>        f.close()
>    except:
>        print 'That file sure is tricky master!
>
>    return (s, 'Whew! here is the file contents, master')

What's above seems simpler. More important, if you do
it this way then you _always_ have to check the return
value of egor_read_file and take appropriate action -
complicates the code everywhere the function is called
as well as making the function more complicated.
Doing it as in UseResource() above you don't need
to worry about whether UseResource() failed
_except_ in situations where you're certain that
that's the right level to catch the error.


>
>> MRAB wrote:
>> You should've used raw strings. :-)
>
>rats!, you got me on that one :-)

David C. Ullrich

"Understanding Godel isn't about following his formal proof. 
That would make a mockery of everything Godel was up to."
(John Jones, "My talk about Godel to the post-grads."
in sci.logic.)



More information about the Python-list mailing list