Re: catching exceptions from an except: block

2007-03-09 Thread Gabriel Genellina
En Fri, 09 Mar 2007 08:14:18 -0300, Gerard Flanagan  
<[EMAIL PROTECTED]> escribió:

> Mea culpa.

Ego te absolvo in nomine Patris Guidii et Filii Python et Spiritus Sancti  
Computatorium.

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-09 Thread Gerard Flanagan
On Mar 9, 11:57 am, "Gabriel Genellina" <[EMAIL PROTECTED]>
wrote:
> En Fri, 09 Mar 2007 07:30:20 -0300, Gerard Flanagan
> <[EMAIL PROTECTED]> escribió:
>
> >> There is a serious flaw on this approach, the function can't return any
> >> false value (it would be treated as a failure).
>
> > I was teaching myself decorators more than anything, so it's not
> > thought out to any extent, but even so I don't think it's a "serious
> > flaw", rather it would be programmer error to use @onfailFalse on a
> > function that may return False. Don't you think?
>
> I thought this was on response to the original problem, not for your own
> problem.
>

Mea culpa.

Gerard



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-09 Thread Gabriel Genellina
En Fri, 09 Mar 2007 07:30:20 -0300, Gerard Flanagan  
<[EMAIL PROTECTED]> escribió:

>> There is a serious flaw on this approach, the function can't return any
>> false value (it would be treated as a failure).
>
> I was teaching myself decorators more than anything, so it's not
> thought out to any extent, but even so I don't think it's a "serious
> flaw", rather it would be programmer error to use @onfailFalse on a
> function that may return False. Don't you think?

I thought this was on response to the original problem, not for your own  
problem.

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-09 Thread Gerard Flanagan
On Mar 9, 9:56 am, "Gabriel Genellina" <[EMAIL PROTECTED]> wrote:
> En Fri, 09 Mar 2007 04:49:59 -0300, Gerard Flanagan
> <[EMAIL PROTECTED]> escribió:
>
> > Another version:
>
> > import exceptions
>
> As back in time as I could go (Python 1.5), exceptions were available as
> builtins...
>

I did not know that. Thanks.

> > def onfailFalse(fn):
> > def inner(*args, **kwargs):
> > try:
> > return fn(*args, **kwargs)
> > except ABCException:
> > return False
> > return inner
>
> > @onfailFalse
> > def a(x):
> > if x == 1:
> > return 'function a succeeded'
> > else:
> > raise ABCException()
>
> There is a serious flaw on this approach, the function can't return any
> false value (it would be treated as a failure).
>

I was teaching myself decorators more than anything, so it's not
thought out to any extent, but even so I don't think it's a "serious
flaw", rather it would be programmer error to use @onfailFalse on a
function that may return False. Don't you think?

Gerard



-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-09 Thread Gabriel Genellina
En Fri, 09 Mar 2007 05:52:35 -0300, Duncan Booth  
<[EMAIL PROTECTED]> escribió:

> "Gabriel Genellina" <[EMAIL PROTECTED]> wrote:
>
>> Not the *previous* exception, but the *current* one. You must be
>> inside an  "except" clause to use a bare raise.
>>
> No, you don't have to be inside an except clause to use a bare raise.
> A bare 'raise' will re-raise the last exception that was active in the
> current scope. That applies even outside the except clauses just so long
> as there has been an exception within the same function:

Oh! Thanks, I didn't know that.
I tested it in the interpreter, outside any function, and the exception  
info was lost immediately, so I wrongly concluded that it lived shortly.

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-09 Thread Gabriel Genellina
En Fri, 09 Mar 2007 04:49:59 -0300, Gerard Flanagan  
<[EMAIL PROTECTED]> escribió:

> Another version:
>
> import exceptions

As back in time as I could go (Python 1.5), exceptions were available as  
builtins...

> def onfailFalse(fn):
> def inner(*args, **kwargs):
> try:
> return fn(*args, **kwargs)
> except ABCException:
> return False
> return inner
>
> @onfailFalse
> def a(x):
> if x == 1:
> return 'function a succeeded'
> else:
> raise ABCException()

There is a serious flaw on this approach, the function can't return any  
false value (it would be treated as a failure).

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-09 Thread Duncan Booth
"Gabriel Genellina" <[EMAIL PROTECTED]> wrote:

> Not the *previous* exception, but the *current* one. You must be
> inside an  "except" clause to use a bare raise.
> 
No, you don't have to be inside an except clause to use a bare raise.

A bare 'raise' will re-raise the last exception that was active in the 
current scope. That applies even outside the except clauses just so long 
as there has been an exception within the same function:

e.g.

def retry(fn, *args):
for attempt in range(3):
try:
return fn(*args)
except:
print "retrying attempt", attempt+1
# If we get here we've had too many retries
raise

>>> import random
>>> def testfn():
if random.randint(0,3):
raise RuntimeError("oops")
return 42

>>> retry(testfn)
retrying attempt 1
retrying attempt 2
retrying attempt 3

Traceback (most recent call last):
  File "", line 1, in 
retry(testfn)
  File "", line 4, in retry
return fn(*args)
  File "", line 3, in testfn
raise RuntimeError("oops")
RuntimeError: oops
>>> retry(testfn)
retrying attempt 1
retrying attempt 2
42
>>> retry(testfn)
42
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Gerard Flanagan
On Mar 8, 10:31 am, "Gabriel Genellina" <[EMAIL PROTECTED]>
wrote:
> En Thu, 08 Mar 2007 06:17:37 -0300, Gerard Flanagan
> <[EMAIL PROTECTED]> escribió:
>
> > @onfail(False)
> > def a(x):
> > if x == 1:
> > return 'function a succeeded'
> > else:
> > raise
>
> I know it's irrelevant, as you use a bare except, but such raise looks a
> bit ugly...
>
> --
> Gabriel Genellina

Agreed. I thought a 'gentle reader' could have filled in the blanks,
but I suppose I should have taken the time to put in a custom
exception.

Another version:

import exceptions

class ABCException(exceptions.Exception):
pass

class DoItException(exceptions.Exception):
pass

def onfailFalse(fn):
def inner(*args, **kwargs):
try:
return fn(*args, **kwargs)
except ABCException:
return False
return inner

@onfailFalse
def a(x):
if x == 1:
return 'function a succeeded'
else:
raise ABCException()

@onfailFalse
def b(x):
if x == 2:
return 'function b succeeded'
else:
raise ABCException()

@onfailFalse
def c(x):
if x == 3:
return 'function c succeeded'
else:
raise ABCException()

def doit(x):
for f in [a, b, c]:
result = f(x)
if result:
return result
raise DoItException()

print doit(1)
print doit(2)
print doit(3)
print doit(4)

-- 
http://mail.python.org/mailman/listinfo/python-list

Re: catching exceptions from an except: block

2007-03-08 Thread Gabriel Genellina
En Thu, 08 Mar 2007 21:11:54 -0300, Steven D'Aprano  
<[EMAIL PROTECTED]> escribió:

>>> @onfail(False)
>>> def a(x):
>>> if x == 1:
>>> return 'function a succeeded'
>>> else:
>>> raise
>
> I thought "raise" on its own was supposed to re-raise the previous
> exception, but I've just tried it in the interactive interpreter and it
> doesn't work for me.

Not the *previous* exception, but the *current* one. You must be inside an  
"except" clause to use a bare raise.

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Paul Rubin
Steven D'Aprano <[EMAIL PROTECTED]> writes:
> Are you saying it only works as advertised within the except clause of a
> try...except block?

I think that's the idea.  It hadn't occurred to me that it could be
used any other way, but I don't have the docs in front of me right
now, so maybe I missed something.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Steven D'Aprano
On Thu, 08 Mar 2007 16:19:27 -0800, Paul Rubin wrote:

> Steven D'Aprano <[EMAIL PROTECTED]> writes:
>> I thought "raise" on its own was supposed to re-raise the previous
>> exception, but I've just tried it in the interactive interpreter and it
>> doesn't work for me.
> 
> It means you can catch an exception, do stuff with it, and then pass
> it upward to earlier callers:

[snip code]

Are you saying it only works as advertised within the except clause of a
try...except block?



-- 
Steven D'Aprano 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Paul Rubin
Steven D'Aprano <[EMAIL PROTECTED]> writes:
> I thought "raise" on its own was supposed to re-raise the previous
> exception, but I've just tried it in the interactive interpreter and it
> doesn't work for me.

It means you can catch an exception, do stuff with it, and then pass
it upward to earlier callers:

def foo(n):
   try:
  bar(n)
   except (ValueError, TypeError):
  print "invalid n:", n
  raise  # re-signal the same error to foo's caler
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Steven D'Aprano
On Thu, 08 Mar 2007 06:31:20 -0300, Gabriel Genellina wrote:

> En Thu, 08 Mar 2007 06:17:37 -0300, Gerard Flanagan  
> <[EMAIL PROTECTED]> escribió:
> 
>> @onfail(False)
>> def a(x):
>> if x == 1:
>> return 'function a succeeded'
>> else:
>> raise
> 
> I know it's irrelevant, as you use a bare except, but such raise looks a  
> bit ugly...


I thought "raise" on its own was supposed to re-raise the previous
exception, but I've just tried it in the interactive interpreter and it
doesn't work for me.

>>> raise ValueError # prime a "previous exception"
Traceback (most recent call last):
  File "", line 1, in ?
ValueError
>>> raise # re-raise the previous exception?
Traceback (most recent call last):
  File "", line 1, in ?
TypeError: exceptions must be classes, instances, or strings (deprecated), not 
NoneType


Have I misunderstood?



-- 
Steven D'Aprano 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Gabriel Genellina
En Thu, 08 Mar 2007 06:17:37 -0300, Gerard Flanagan  
<[EMAIL PROTECTED]> escribió:

> @onfail(False)
> def a(x):
> if x == 1:
> return 'function a succeeded'
> else:
> raise

I know it's irrelevant, as you use a bare except, but such raise looks a  
bit ugly...

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Gerard Flanagan
On Mar 7, 7:32 pm, "Arnaud Delobelle" <[EMAIL PROTECTED]> wrote:
> 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.
>


(This is my first decorator.)  You could also just raise your custom
exception rather than having a "retval". Other variations I'm sure are
possible. HTH.


import exceptions

class ABCException(exceptions.Exception):
pass

def onfail(retval):
def outer(fn):
def inner(*args, **kwargs):
try:
return fn(*args, **kwargs)
except:
return retval
return inner
return outer

@onfail(False)
def a(x):
if x == 1:
return 'function a succeeded'
else:
raise

@onfail(False)
def b(x):
if x == 2:
return 'function b succeeded'
else:
raise

@onfail(False)
def c(x):
if x == 3:
return 'function c succeeded'
else:
raise

def doit(x):
for f in [a, b, c]:
result = f(x)
if result:
return result
raise ABCException()

print doit(1)
print doit(2)
print doit(3)
print doit(4)

---

function a succeeded
function b succeeded
function c succeeded
Traceback (most recent call last):
  File "\working\scratch.py", line 48, in ?
print doit(4)
  File "\working\scratch.py", line 43, in doit
raise ABCException()
__main__.ABCException
shell returned 1




-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-08 Thread Bruno Desthuilliers
MonkeeSage a écrit :
> On Mar 7, 4:58 pm, Bruno Desthuilliers
> <[EMAIL PROTECTED]> wrote:
>>except_retry: # the missing(???) keyword you're after
> 
> What is 'except_retry'?

A totally imaginary statement that would do what the OP is looking for.

> To the OP, with the loop and the callables you could also break out of
> the loop when the condition is met and use the else condition to raise
> the exception.
> 
> def test(arg):
> for f in int, float, str, hex:
> try:
> return f(arg)
> break # breaks on f==str

You don't need to break here since you're returning.

> except:
> pass
> else:
> raise ValueError # remove str above to see this
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Steven D'Aprano
On Wed, 07 Mar 2007 10:32:53 -0800, Arnaud Delobelle wrote:

> 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
> def nested_first(x):
> try:
> return a(x)
> except:
> try:
> return b(x)
> except:
> try:
> return c(x)
> except:
> raise CantDoIt


Exceptions are great, but sometimes they get in the way. This is one of
those times.

NULL = object() # get a unique value
def result_or_special(func, x):
"""Returns the result of func(x) or NULL."""
try:
return func(x)
except Exception:
return NULL

def failer(x):
"""Always fail."""
raise CantDoIt

def function(x):
funcs = (a, b, c, failer)
for func in funcs:
result = func(x)
if result is not NULL: break
return result


Or if you prefer:

def function(x):
NULL = object()
funcs = (a, b, c)
for func in funcs:
try:
result = func(x)
except Exception:
pass
else:
break
else:
# we didn't break out of the loop
raise CantDoIt
# we did break out of the loop
return result



-- 
Steven D'Aprano 

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread MonkeeSage
On Mar 7, 4:58 pm, Bruno Desthuilliers
<[EMAIL PROTECTED]> wrote:
>except_retry: # the missing(???) keyword you're after

What is 'except_retry'?

To the OP, with the loop and the callables you could also break out of
the loop when the condition is met and use the else condition to raise
the exception.

def test(arg):
for f in int, float, str, hex:
try:
return f(arg)
break # breaks on f==str
except:
pass
else:
raise ValueError # remove str above to see this
print test('^&%')

Regards,
Jordan


-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Diez B. Roggisch
Arnaud Delobelle schrieb:
> On Mar 7, 8:52 pm, Larry Bates <[EMAIL PROTECTED]> wrote:
> [snip]
>> Without knowing more about the functions and the variable it is somewhat
>> hard to tell what you are trying to accomplish.  If a, b, c are functions
>> that act on x when it is a different type, change to one function that
>> can handle all types.
> 
> I'm not really thinking about this situation so let me clarify. Here
> is a simple concrete example, taking the following for the functions
> a,b,c I mention in my original post.
>   - a=int
>   - b=float
>   - c=complex
>   - x is a string
> This means I want to convert x to an int if possible, otherwise a
> float, otherwise a complex, otherwise raise CantDoIt.
> 
> I can do:
> 
> for f in int, float, complex:
> try:
> return f(x)
> except ValueError:
> continue
> raise CantDoIt
> 
> But if the three things I want to do are not callable objects but
> chunks of code this method is awkward because you have to create
> functions simply in order to be able to loop over them (this is whay I
> was talking about 'abusing loop constructs').  

In your case, I don't consider it an abuse - au contraire. Because in 
such a situation where a possibly growing number of functions dealing 
with one value until one of them "fits" a loop is the natural thing to 
do, as it won't change in appearance just because you add a new 
conversion-function to some (semi-)global list. I'd consider it 
especially good style in that case.

Diez
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Bruno Desthuilliers
Gabriel Genellina a écrit :
> En Wed, 07 Mar 2007 18:48:18 -0300, Arnaud Delobelle  
> <[EMAIL PROTECTED]> escribió:
> 
>> for f in int, float, complex:
>> try:
>> return f(x)
>> except ValueError:
>> continue
>> raise CantDoIt
>>
>> But if the three things I want to do are not callable objects but
>> chunks of code this method is awkward because you have to create
>> functions simply in order to be able to loop over them (this is whay I
>> was talking about 'abusing loop constructs').  Besides I am not happy
>> with the other two idioms I can think of.
> 
> 
> Hmmm, functions are cheap 

To define. You pay the price when you call them !-)

(sorry, couldn't resist - I otherwise totally agree with you)

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Bruno Desthuilliers
Arnaud Delobelle a écrit :
> On Mar 7, 8:52 pm, Larry Bates <[EMAIL PROTECTED]> wrote:
> [snip]
> 
>>Without knowing more about the functions and the variable it is somewhat
>>hard to tell what you are trying to accomplish.  If a, b, c are functions
>>that act on x when it is a different type, change to one function that
>>can handle all types.
> 
> 
> I'm not really thinking about this situation so let me clarify. Here
> is a simple concrete example, taking the following for the functions
> a,b,c I mention in my original post.
>   - a=int
>   - b=float
>   - c=complex
>   - x is a string
> This means I want to convert x to an int if possible, otherwise a
> float, otherwise a complex, otherwise raise CantDoIt.
> 
> I can do:
> 
> for f in int, float, complex:
> try:
> return f(x)
> except ValueError:
> continue
> raise CantDoIt
> 
> But if the three things I want to do are not callable objects but
> chunks of code this method is awkward because you have to create
> functions 

You have to write the "chunks of code" anyway, don't you ? So just 
adding a def statement above each chunk is not such a big deal.

Remember that you can define nested funcs, that will close over the 
namespace of the enclosing one, so you dont necessarily have to pollute 
the global namespace nor explicitly pass the whole environment to each 
of these functions.

Using the generic higher order func I proposed in a previous answer:

def maincode(tati, pouffin):
   def a():
 # some
 # code
 # here
 # that may raise
 return foo

   def b():
 # some
 # shorter chunk
 return bar

   def c():
 # yet
 # some
 # other
 # code
 return quux

   return trythese(a, b)()

Is it really less readable than:

def maincode(tati, pouffin):
   try:
 # some
 # code
 # here
 # that may raise
 return foo

   except_retry: # the missing(???) keyword you're after
 # some
 # shorter chunk
 return bar

   except_retry:
 # yet
 # some
 # other
 # code
 return quux

   else:
 raise CantDoIt


> simply in order to be able to loop over them (this is whay I
> was talking about 'abusing loop constructs').  Besides I am not happy
> with the other two idioms I can think of.
> 
> --
> Arnaud
> 
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Gabriel Genellina
En Wed, 07 Mar 2007 18:48:18 -0300, Arnaud Delobelle  
<[EMAIL PROTECTED]> escribió:

> for f in int, float, complex:
> try:
> return f(x)
> except ValueError:
> continue
> raise CantDoIt
>
> But if the three things I want to do are not callable objects but
> chunks of code this method is awkward because you have to create
> functions simply in order to be able to loop over them (this is whay I
> was talking about 'abusing loop constructs').  Besides I am not happy
> with the other two idioms I can think of.

Hmmm, functions are cheap - nobody is charging you $2 for each "def"  
statement you write, I presume :)

A bit more serious, if those "chunks of code" are processing its input and  
returning something that you further process... they *are* functions. If  
you don't want them to be publicly available, use inner functions:

def xxxfactory(x):
   def f1(x):
  ...
   def f2(x):
  ...
   def f3(x):
  ...

   for f in f1,f2,f3:
 try:
   return f(x)
   ... same as above...

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread garrickp
On Mar 7, 3:04 pm, [EMAIL PROTECTED] wrote:
> On Mar 7, 2:48 pm, "Arnaud Delobelle" <[EMAIL PROTECTED]> wrote:
>
>
>
>
>
> > I'm not really thinking about this situation so let me clarify. Here
> > is a simple concrete example, taking the following for the functions
> > a,b,c I mention in my original post.
> >   - a=int
> >   - b=float
> >   - c=complex
> >   - x is a string
> > This means I want to convert x to an int if possible, otherwise a
> > float, otherwise a complex, otherwise raise CantDoIt.
>
> > I can do:
>
> > for f in int, float, complex:
> > try:
> > return f(x)
> > except ValueError:
> > continue
> > raise CantDoIt
>
> > But if the three things I want to do are not callable objects but
> > chunks of code this method is awkward because you have to create
> > functions simply in order to be able to loop over them (this is whay I
> > was talking about 'abusing loop constructs').  Besides I am not happy
> > with the other two idioms I can think of.
>
> > --
> > Arnaud
>
> Wouldn't it be easier to do:
>
> if isinstance(x, int):
> # do something
> elif isinstance(x, float)t:
> # do something
> elif isinstance(x, complex):
> # do something
> else:
> raise CantDoIt
>
> or,
>
> i = [int, float, complex]
> for f in i:
> if isinstance(x, f):
> return x
> else:
> raise CantDoIt

I so missed the point of this. Not my day. Please ignore my post.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Bruno Desthuilliers
Gabriel Genellina a écrit :
> En Wed, 07 Mar 2007 19:00:59 -0300, Bruno Desthuilliers  
> <[EMAIL PROTECTED]> escribió:
> 
>> this kind of cose is exactly what OO polymorphic dispatch is supposed to
> 
> 
> this kind of cose?

sorry
s/cose/code/

> Ce genre de chose?
> 
En quelques sortes, oui, quoique pas tout à fait !-)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread garrickp
On Mar 7, 2:48 pm, "Arnaud Delobelle" <[EMAIL PROTECTED]> wrote:
>
> I'm not really thinking about this situation so let me clarify. Here
> is a simple concrete example, taking the following for the functions
> a,b,c I mention in my original post.
>   - a=int
>   - b=float
>   - c=complex
>   - x is a string
> This means I want to convert x to an int if possible, otherwise a
> float, otherwise a complex, otherwise raise CantDoIt.
>
> I can do:
>
> for f in int, float, complex:
> try:
> return f(x)
> except ValueError:
> continue
> raise CantDoIt
>
> But if the three things I want to do are not callable objects but
> chunks of code this method is awkward because you have to create
> functions simply in order to be able to loop over them (this is whay I
> was talking about 'abusing loop constructs').  Besides I am not happy
> with the other two idioms I can think of.
>
> --
> Arnaud

Wouldn't it be easier to do:

if isinstance(x, int):
# do something
elif isinstance(x, float)t:
# do something
elif isinstance(x, complex):
# do something
else:
raise CantDoIt

or,

i = [int, float, complex]
for f in i:
if isinstance(x, f):
return x
else:
raise CantDoIt

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Bruno Desthuilliers
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:


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.


> 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 (it still 
lacks a way to specify which kind of exceptions should be silently 
swallowed.

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.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Arnaud Delobelle
On Mar 7, 8:52 pm, Larry Bates <[EMAIL PROTECTED]> wrote:
[snip]
> Without knowing more about the functions and the variable it is somewhat
> hard to tell what you are trying to accomplish.  If a, b, c are functions
> that act on x when it is a different type, change to one function that
> can handle all types.

I'm not really thinking about this situation so let me clarify. Here
is a simple concrete example, taking the following for the functions
a,b,c I mention in my original post.
  - a=int
  - b=float
  - c=complex
  - x is a string
This means I want to convert x to an int if possible, otherwise a
float, otherwise a complex, otherwise raise CantDoIt.

I can do:

for f in int, float, complex:
try:
return f(x)
except ValueError:
continue
raise CantDoIt

But if the three things I want to do are not callable objects but
chunks of code this method is awkward because you have to create
functions simply in order to be able to loop over them (this is whay I
was talking about 'abusing loop constructs').  Besides I am not happy
with the other two idioms I can think of.

--
Arnaud

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Gabriel Genellina
En Wed, 07 Mar 2007 19:00:59 -0300, Bruno Desthuilliers  
<[EMAIL PROTECTED]> escribió:

> this kind of cose is exactly what OO polymorphic dispatch is supposed to

this kind of cose? Ce genre de chose?

-- 
Gabriel Genellina

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Bruno Desthuilliers
Larry Bates a écrit :
(snip)

> def d(x):
> if isinstance(x, basestring):
> #
> # Code here for string
> #
> elif isinstance(x, int):
> #
> # Code here for int
> #
> elif isinstance(x, float):
> #
> # Code here for string
> #
> else:
> raise ValueError

As a side note : While there are a few corner cases where this is hardly 
avoidable (and yet I'd rather test on interface, not on concrete type), 
this kind of cose is exactly what OO polymorphic dispatch is supposed to 
avoid (no, don't tell me: I know you can't easily add methods to most 
builtin types).
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Bruno Desthuilliers
Miki a écrit :
> Hello Arnaud,
> 
> 
>>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.
> 
> Exceptions are for error handling, not flow control.

def until(iterable,sentinel):
   for item in iterable:
 if item == sentinel:
   raise StopIteration
 yield item

 >>> for item in until(range(10), 5):
... print item
...
0
1
2
3
4
 >>>

Exceptions *are* a form of flow control.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Larry Bates
Arnaud Delobelle wrote:
> 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
> def nested_first(x):
> try:
> return a(x)
> except:
> try:
> return b(x)
> except:
> try:
> return c(x)
> except:
> raise CantDoIt
> 
> # This one looks long-winded
> 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
> # Moreover it seems like an abuse of a loop construct to me
> def rolled_first(x):
> for f in a, b, c:
> try:
> return f(x)
> except:
> continue
> raise CantDoIt
> --
> 
> I don't feel happy with any of these.  Is there a more satisfying way
> of doing this in Python? What I would like is something like:
> 
> --
> # 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
> --
> 
> I guess what I'm looking for is some sort of
> if:
> elif:
> ...
> elif:
> else:
> 
> but for try: except:
> That's why
> try:
> except:
> except:
> ...
> except:
> 
> seemed natural to me :)  And I'd like to find a nice way to do this in
> a syntactically correct way.
> 
> Note: I've chosen functions a, b, c, but really I'm looking for a way
> that is suitable for any chunk of code.
> 
Without knowing more about the functions and the variable it is somewhat
hard to tell what you are trying to accomplish.  If a, b, c are functions
that act on x when it is a different type, change to one function that
can handle all types.

def d(x):
if isinstance(x, basestring):
#
# Code here for string
#
elif isinstance(x, int):
#
# Code here for int
#
elif isinstance(x, float):
#
# Code here for string
#
else:
raise ValueError


If they are different functions based on type do something like this:

#
# Set up a dictionary with keys for different types and functions
# that correspond.
#
fdict={type(''): a, type(1): b, type(1.0): c}
#
# Call the appropriate function based on type
#
fdict[type(x)](x)

-Larry
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Marc 'BlackJack' Rintsch
In <[EMAIL PROTECTED]>, Miki wrote:

> Exceptions are for error handling, not flow control.

That's not true, they are *exceptions* not *errors*.  They are meant to
signal exceptional situations.  And at least under the cover it's used in
every ``for``-loop because the end condition is signaled by a
`StopIteration` exception.  Looks like flow control to me.

Ciao,
Marc 'BlackJack' Rintsch
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Marc 'BlackJack' Rintsch
In <[EMAIL PROTECTED]>, Arnaud Delobelle
wrote:

> # This one only works because a,b,c are functions
> # Moreover it seems like an abuse of a loop construct to me
> def rolled_first(x):
> for f in a, b, c:
> try:
> return f(x)
> except:
> continue
> raise CantDoIt
> --

Why do you think this is an abuse?  I think it's a perfectly valid use of
a loop.

Ciao,
Marc 'BlackJack' Rintsch
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Arnaud Delobelle
On 7 Mar, 19:26, "Miki" <[EMAIL PROTECTED]> wrote:
> Hello Arnaud,

Hi Miki

[snip]
> Exceptions are for error handling, not flow control.

Maybe but it's not always that clear cut! As error handling is a form
of flow control the two have to meet somewhere.

[snip]
> As a side note, try to avoid "catch:", always catch explicit
> exceptions.

I didn't specify what I wanted to catch because it didn't feel it was
relevant to the problem.

Thanks

--
Arnaud

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: catching exceptions from an except: block

2007-03-07 Thread Miki
Hello Arnaud,

> 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.
Exceptions are for error handling, not flow control.

> Here are three ways I can think of doing it:
> ...

> # This one only works because a,b,c are functions
> # Moreover it seems like an abuse of a loop construct to me
> def rolled_first(x):
> for f in a, b, c:
> try:
> return f(x)
> except:
> continue
> raise CantDoIt
My vote is for that one.

> I don't feel happy with any of these.  Is there a more satisfying way
> of doing this in Python? What I would like is something like:
>
> --
> # 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
Again, exception are for error handling, not for flow control.

As a side note, try to avoid "catch:", always catch explicit
exceptions.

HTH,
Miki <[EMAIL PROTECTED]>
http://pythonwise.blogspot.com

-- 
http://mail.python.org/mailman/listinfo/python-list