[Tutor] What's the best way to ask forgiveness here?

Adam Bark adam.jtm30 at gmail.com
Mon Sep 13 21:07:33 CEST 2010


On 13/09/10 19:31, Brian Jones wrote:
> I've been coding Python long enough that 'asking forgiveness instead 
> of permission' is my first instinct, but the resulting code is 
> sometimes clumsy, and I wonder if someone can suggest something I'm 
> missing, or at least validate what's going on here in some way.
>
> What I'm trying to do is write a file to a directory. However, the 
> directory may not exist the first time I try to write a file there, so 
> I'm going to first try to write the file, and if I get an exception, 
> create the directory (er, *try* to), and *then* write the file there. 
> Here's my first shot at the code:
>
>         try:
>             self.save_file(picfile_fullpath, picdata)
>         except IOError as err:
>             # directory doesn't exist. Try to create it.
>             try:
>                 os.makedirs(picfile_fullpath)
>             except OSError as oserr:
>                 logging.error("Can't create file path: %s (%s)" % 
> (picfile_fullpath, oserr))
>             else:
>                 # Created dir, now write file.
>                 try:
>                     self.save_file(picfile_fullpath, picdata)
>                 except IOError as err:
>                     logging.error("Bailing. Couldn't save file %s 
> (%s)" % (picfile_fullpath, err))
>                     return False
>
> Doesn't this seem less readable than the 'ask permission' equivalent? 
> I think it does, but in this case asking permission for every single 
> operation when the dir will only need to be created a single time (and 
> then may be written to several hundred times) is pretty wasteful.
>
> I suppose I could set some sentinel variable and check for it in a 
> while loop, but then I need some other scaffolding code to make sure I 
> don't infinitely loop trying to create the directory, and probably 
> some other stuff I'm forgetting, so it strikes me as being just as messy.
>
> Is there a clean sort of pattern to apply in instances like this?
>
> Thanks.
> brian

How about something like this?

try:
     os.makedirs(picfile_fullpath)
     self.save_file(picfile_fullpath, picdata)
except IOError, OSError as err:
     if type(err) is OSError:
         logging.error("Can't create file path: %s (%s)" % 
(picfile_fullpath, oserr))
         try:
             self.save_file(picfile_fullpath, picdata)
         except IOError:
             logging.error("Bailing. Couldn't save file %s (%s)" % 
(picfile_fullpath, err))
     else:
         logging.error("Bailing. Couldn't save file %s (%s)" % 
(picfile_fullpath, err))

This saves you one try except and the else although it adds an if else. 
Either way it's not as far nested.
I just thought up another way that just takes two try excepts:

try:
     try:
         os.makedirs(picfile_fullpath)
         self.save_file(picfile_fullpath, picdata)
     except OSError as oserr:
         logging.error("Can't create file path: %s (%s)" % 
(picfile_fullpath, oserr))
         self.save_file(picfile_fullpath, picdata)
except IOError as err:
     logging.error("Bailing. Couldn't save file %s (%s)" % 
(picfile_fullpath, err))
     return False

HTH


More information about the Tutor mailing list