catching exceptions from an except: block

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Wed Mar 7 17:33:00 EST 2007


Arnaud Delobelle a écrit :
> Hi all,
> 
> Imagine I have three functions a(x), b(x), c(x) that each return
> something or raise an exception.  Imagine I want to define a function
> that returns a(x) if possible, otherwise b(x), otherwise c(x),
> otherwise raise CantDoIt.
> 
> Here are three ways I can think of doing it:
> 
> ----------
> # This one looks ugly

Yes.

> def nested_first(x):
>     try:
>         return a(x)
>     except:

<side-note>
Try avoiding bare except clauses. It's usually way better to specify the 
type(s) of exception you're expecting to catch, and let other propagate.
</side-note>

>         try:
>             return b(x)
>         except:
>             try:
>                 return c(x)
>             except:
>                 raise CantDoIt
> 
> # This one looks long-winded

Yes. And not's very generic.

> def flat_first(x):
>     try:
>         return a(x)
>     except:
>         pass
>     try:
>         return b(x)
>     except:
>         pass
>     try:
>         return c(x)
>     except:
>         raise CantDoIt
> 
> # This one only works because a,b,c are functions

It works with any callable. Anyway, what else would you use here ???

> # Moreover it seems like an abuse of a loop construct to me

Why so ? loops are made for looping, adn functions are objects like any 
other.

> def rolled_first(x):
>     for f in a, b, c:
>         try:
>             return f(x)
>         except:
>             continue
>     raise CantDoIt

Here's an attempt at making it a bit more generic (<side-note>it still 
lacks a way to specify which kind of exceptions should be silently 
swallowed</side-note>.

def trythese(*functions):
   def try_(*args, **kw):
     for func in functions:
        try:
          return func(*args, **kw)
        except: # FIX ME : bare except clause
          pass
     else:
       # really can't do it, sorry
       raise CantDoIt
   return try_

result = trythese(a, b, c)(x)

> ----------
> # This one isn't correct but looks the clearest to me
> def wished_first(x):
>     try:
>         return a(x)
>     except:
>         return b(x)
>     except:
>         return c(x)
>     except:
>         raise CantDoIt

Having multiple except clauses is correct - but it has another semantic.


> Note: I've chosen functions a, b, c, but really I'm looking for a way
> that is suitable for any chunk of code.

A function is an object wrapping a chunk of code...

I personnaly find the loop-based approach quite clean and pythonic.



More information about the Python-list mailing list