473,396 Members | 1,998 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

catching exceptions from an except: block

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.

Mar 7 '07 #1
35 1970
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 <mi*********@gmail.com>
http://pythonwise.blogspot.com

Mar 7 '07 #2
On 7 Mar, 19:26, "Miki" <miki.teb...@gmail.comwrote:
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

Mar 7 '07 #3
In <11**********************@8g2000cwh.googlegroups.c om>, 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
Mar 7 '07 #4
In <11**********************@p10g2000cwp.googlegroups .com>, 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
Mar 7 '07 #5
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
Mar 7 '07 #6
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.
Mar 7 '07 #7
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).
Mar 7 '07 #8
En Wed, 07 Mar 2007 19:00:59 -0300, Bruno Desthuilliers
<bd*****************@free.quelquepart.frescribió :
this kind of cose is exactly what OO polymorphic dispatch is supposed to
this kind of cose? Ce genre de chose?

--
Gabriel Genellina

Mar 7 '07 #9
On Mar 7, 8:52 pm, Larry Bates <lba...@websafe.comwrote:
[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

Mar 7 '07 #10
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.
Mar 7 '07 #11
On Mar 7, 2:48 pm, "Arnaud Delobelle" <arno...@googlemail.comwrote:
>
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

Mar 7 '07 #12
Gabriel Genellina a écrit :
En Wed, 07 Mar 2007 19:00:59 -0300, Bruno Desthuilliers
<bd*****************@free.quelquepart.frescribió :
>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 !-)
Mar 7 '07 #13
On Mar 7, 3:04 pm, garri...@gmail.com wrote:
On Mar 7, 2:48 pm, "Arnaud Delobelle" <arno...@googlemail.comwrote:


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.

Mar 7 '07 #14
En Wed, 07 Mar 2007 18:48:18 -0300, Arnaud Delobelle
<ar*****@googlemail.comescribió:
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

Mar 7 '07 #15
Arnaud Delobelle a écrit :
On Mar 7, 8:52 pm, Larry Bates <lba...@websafe.comwrote:
[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
Mar 7 '07 #16
Gabriel Genellina a écrit :
En Wed, 07 Mar 2007 18:48:18 -0300, Arnaud Delobelle
<ar*****@googlemail.comescribió:
>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)

Mar 7 '07 #17
Arnaud Delobelle schrieb:
On Mar 7, 8:52 pm, Larry Bates <lba...@websafe.comwrote:
[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
Mar 7 '07 #18
On Mar 7, 4:58 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.frwrote:
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
Mar 8 '07 #19
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

Mar 8 '07 #20
MonkeeSage a écrit :
On Mar 7, 4:58 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.frwrote:
> 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
Mar 8 '07 #21
On Mar 7, 7:32 pm, "Arnaud Delobelle" <arno...@googlemail.comwrote:
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


Mar 8 '07 #22
En Thu, 08 Mar 2007 06:17:37 -0300, Gerard Flanagan
<gr********@yahoo.co.ukescribió:
@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

Mar 8 '07 #23
On Thu, 08 Mar 2007 06:31:20 -0300, Gabriel Genellina wrote:
En Thu, 08 Mar 2007 06:17:37 -0300, Gerard Flanagan
<gr********@yahoo.co.ukescribió:
>@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 "<stdin>", line 1, in ?
ValueError
>>raise # re-raise the previous exception?
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: exceptions must be classes, instances, or strings (deprecated), not NoneType
Have I misunderstood?

--
Steven D'Aprano

Mar 9 '07 #24
Steven D'Aprano <st***@REMOVEME.cybersource.com.auwrites:
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
Mar 9 '07 #25
On Thu, 08 Mar 2007 16:19:27 -0800, Paul Rubin wrote:
Steven D'Aprano <st***@REMOVEME.cybersource.com.auwrites:
>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

Mar 9 '07 #26
Steven D'Aprano <st***@REMOVEME.cybersource.com.auwrites:
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.
Mar 9 '07 #27
En Thu, 08 Mar 2007 21:11:54 -0300, Steven D'Aprano
<st***@REMOVEME.cybersource.com.auescribió:
>>@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

Mar 9 '07 #28
On Mar 8, 10:31 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
En Thu, 08 Mar 2007 06:17:37 -0300, Gerard Flanagan
<grflana...@yahoo.co.ukescribió:
@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)

Mar 9 '07 #29
"Gabriel Genellina" <ga*******@yahoo.com.arwrote:
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 "<pyshell#24>", line 1, in <module>
retry(testfn)
File "<pyshell#20>", line 4, in retry
return fn(*args)
File "<pyshell#23>", line 3, in testfn
raise RuntimeError("oops")
RuntimeError: oops
>>retry(testfn)
retrying attempt 1
retrying attempt 2
42
>>retry(testfn)
42
Mar 9 '07 #30
En Fri, 09 Mar 2007 04:49:59 -0300, Gerard Flanagan
<gr********@yahoo.co.ukescribió:
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

Mar 9 '07 #31
En Fri, 09 Mar 2007 05:52:35 -0300, Duncan Booth
<du**********@invalid.invalidescribió:
"Gabriel Genellina" <ga*******@yahoo.com.arwrote:
>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

Mar 9 '07 #32
On Mar 9, 9:56 am, "Gabriel Genellina" <gagsl-...@yahoo.com.arwrote:
En Fri, 09 Mar 2007 04:49:59 -0300, Gerard Flanagan
<grflana...@yahoo.co.ukescribió:
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

Mar 9 '07 #33
En Fri, 09 Mar 2007 07:30:20 -0300, Gerard Flanagan
<gr********@yahoo.co.ukescribió:
>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

Mar 9 '07 #34
On Mar 9, 11:57 am, "Gabriel Genellina" <gagsl-...@yahoo.com.ar>
wrote:
En Fri, 09 Mar 2007 07:30:20 -0300, Gerard Flanagan
<grflana...@yahoo.co.ukescribió:
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

Mar 9 '07 #35
En Fri, 09 Mar 2007 08:14:18 -0300, Gerard Flanagan
<gr********@yahoo.co.ukescribió:
Mea culpa.
Ego te absolvo in nomine Patris Guidii et Filii Python et Spiritus Sancti
Computatorium.

--
Gabriel Genellina

Mar 9 '07 #36

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Keith Bolton | last post by:
I am handling exceptions currently using try, except. Generally I don't handle specific exceptions and am catching all. Then if an exception occurs, I would like to capture that error string....
8
by: Adam H. Peterson | last post by:
Hello, I sometimes find myself writing code something like this: try { Derived &d=dynamic_cast<Derived&>(b); d.do_something_complicated(); // etc.... } catch (std::bad_cast) { throw...
4
by: a_geek | last post by:
Hello, I'd like to catch all exeptions and be able to inspect them. The simple case: I know which exceptions I'll get: # standard textbook example: try: something() except ThisException,...
7
by: cmay | last post by:
FxCop complains every time I catch System.Exception. I don't see the value in trying to catch every possible exception type (or even figuring out what exceptions can be caught) by a given block...
12
by: Vasco Lohrenscheit | last post by:
Hi, I have a Problem with unmanaged exception. In the debug build it works fine to catch unmanaged c++ exceptions from other dlls with //managed code: try { //the form loads unmanaged dlls...
7
by: Derek Schuff | last post by:
I'm sorry if this is a FAQ or on an easily-accesible "RTFM" style page, but i couldnt find it. I have some code like this: for line in f: toks = line.split() try: if int(toks,16) ==...
5
by: Simon Tamman | last post by:
I have an object named DisasterRecovery. The Ctor of this object is this: private DisasterRecovery() { Application.ThreadException+= new...
12
by: Karlo Lozovina | last post by:
I'm not sure if Python can do this, and I can't find it on the web. So, here it goes: try: some_function() except SomeException: some_function2() some_function3() ...
3
by: john | last post by:
I wrapped some fortran code using F2PY and need to be able to catch fortran runtime errors to run the following: # "grid" is a wrapped fortran module # no runtime errors incurred when run with...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.