Abuse of the object-nature of functions?

A

Ant

Hi all,

In a framework I've written to test out website, I use something like
the following to add functionality at various points:

#-----------------------------------
def do_work(callable, data):
assertion = False
try:
assertion = callable.is_assertion
except:
pass

out = callable(data)

if assertion:
print "Test " % ("Failed", "Suceeded")[out]

return out

def get_assn(fn):
def wrapper(*args, **kw):
return fn(*args, **kw)
out = wrapper
out.is_assertion = True
return out

def funct(data):
return True

x = funct
y = get_assn(funct)

do_work(x, data)
do_work(y, data)

#-----------------------------------

The idea is that I can mark some functions as being assertions, and use
the same function for applying the callable to the data and optionally
printing some information. This way I needn't worry whether the
callable is a custom object or a simple function.

The question is, is this a reasonable thing to do? It works, but is it
considered bad practice to add attributes to functions? And are there
any dangers?
 
F

Fredrik Lundh

Ant said:
The question is, is this a reasonable thing to do?

absolutely. a test framework "DSL" is a perfectly valid use case for
function attributes.
It works, but is it considered bad practice to add attributes to functions?

nope (at least not in small doses ;-)
And are there any dangers?

nope.

</F>
 
S

Sybren Stuvel

Ant enlightened us with:
try:
assertion = callable.is_assertion
except:
pass

Try to make a habit out of catching only the exceptions you know will
be thrown. Catching everything generally is a bad idea. In this case,
my bet is that catching AttributeError is enough.

Sybren
 
F

Fredrik Lundh

Sybren said:
Ant enlightened us with:

Try to make a habit out of catching only the exceptions you know will
be thrown. Catching everything generally is a bad idea. In this case,
my bet is that catching AttributeError is enough.

and

assertion = hasattr(callable, "is_assertion")

is even nicer (and can be done as part of the if-statement after the call, in-
stead of in a separate try/except before the call)

</F>
 
P

Peter Otten

Fredrik said:
and

assertion = hasattr(callable, "is_assertion")

is even nicer (and can be done as part of the if-statement after the call,
in- stead of in a separate try/except before the call)

You would normally expect that you can turn off a flag by setting it to
False instead of deleting it -- which is also how the OP's code works. So I
would prefer

assertion = getattr(callable, "is_assertion", False)

if you forgo the explicit try...except.

Peter
 
F

Fredrik Lundh

Peter said:
You would normally expect that you can turn off a flag by setting it to
False instead of deleting it -- which is also how the OP's code works. So I
would prefer

assertion = getattr(callable, "is_assertion", False)

agreed (but note that the OP used a decorator to set the attribute, so you could
consider it an implementation detail...)

</F>
 
A

Ant

Sybren said:
Try to make a habit out of catching only the exceptions you know will
be thrown.

Yes - you are right of course - this was just a minimal example of
course to illustrate the sort of thing I'm using function attriutes
for.


I like this way of doing it, as it is possible I may have a function
that could feasibly be either an assertion or otherwise depending on
context.
agreed (but note that the OP used a decorator to set the attribute, so you could
consider it an implementation detail...)

The main reason for using a decorator was to avoid problems like the
following whilst providing an easy way of adding the attribute:
.... return False
....True
 
C

Carl J. Van Arsdall

Sybren said:
Ant enlightened us with:


Try to make a habit out of catching only the exceptions you know will
be thrown. Catching everything generally is a bad idea. In this case,
my bet is that catching AttributeError is enough.
What about doing exception kind of like a C switch statement with a
default case:

try:
do_something()
except TypeError:
fix_something()
except:
print "Unknown error, you are doomed"
traceback.print_exc() #something to print the traceback
exit_gracefully()

Is this frowned upon? You still handle the error and you know where it
happened and what happened. Anything wrong with this? I don't like the
idea of my system crashing for any reason.

-carl


--

Carl J. Van Arsdall
(e-mail address removed)
Build and Release
MontaVista Software
 
B

Bruno Desthuilliers

Carl said:
What about doing exception kind of like a C switch statement with a
default case:

try:
do_something()
except TypeError:
fix_something()
except:
print "Unknown error, you are doomed"
traceback.print_exc() #something to print the traceback
exit_gracefully()

Is this frowned upon? You still handle the error and you know where it
happened and what happened. Anything wrong with this? I don't like the
idea of my system crashing for any reason.

It may be a good idea to do something like this *at the top level of the
application*. But take time to carefully read the standard exceptions
hierarchy in the fine manual - you'll notice some exception you perhaps
don't want to catch or at least don't want to display (hint: look for
the warnings hierarchy and for SysExit...)
 
C

Carl J. Van Arsdall

Bruno said:
It may be a good idea to do something like this *at the top level of the
application*. But take time to carefully read the standard exceptions
hierarchy in the fine manual - you'll notice some exception you perhaps
don't want to catch or at least don't want to display (hint: look for
the warnings hierarchy and for SysExit...)
Hrmms, well, here's an interesting situation. So say we wanna catch
most exceptions but we don't necessarily know what they are going to
be. For example, I have a framework that executes modules (python
functions), the framework wraps each function execution in a try/except
block in order to compensate for what *might* happen. Upon coding the
framework I really have no idea what types of problems these modules
might have but I want to catch these errors so that I can clean up and
exit gracefully, not only that but I want to dump the exception to log
files so that we can attempt to fix it. So, I have the option of
catching all standard exceptions and not list the ones I know I don't
want to catch. But what about user defined exceptions? Do I then have
to enforce policies on the system stating what types of exceptions can
be raised?

Is there a way in python to say, "hey, catch everything but these two"?



--

Carl J. Van Arsdall
(e-mail address removed)
Build and Release
MontaVista Software
 
A

Ant

Is there a way in python to say, "hey, catch everything but these two"?
.... raise AttributeError
.... except Exception, ex:
.... if isinstance(ex, AttributeError):
.... print "Won't catch it!"
.... raise ex
....

Won't catch it!
Traceback (most recent call last):
File "<stdin>", line 7, in ?
AttributeError

Or that sort of thing.
 
S

Simon Forman

Carl said:
Hrmms, well, here's an interesting situation. So say we wanna catch
most exceptions but we don't necessarily know what they are going to
be. For example, I have a framework that executes modules (python
functions), the framework wraps each function execution in a try/except
block in order to compensate for what *might* happen. Upon coding the
framework I really have no idea what types of problems these modules
might have but I want to catch these errors so that I can clean up and
exit gracefully, not only that but I want to dump the exception to log
files so that we can attempt to fix it. So, I have the option of
catching all standard exceptions and not list the ones I know I don't
want to catch. But what about user defined exceptions? Do I then have
to enforce policies on the system stating what types of exceptions can
be raised?

Is there a way in python to say, "hey, catch everything but these two"?



--

Carl J. Van Arsdall
(e-mail address removed)
Build and Release
MontaVista Software


try:
# Do some stuff
except Exception, err:
if err not in (DontCatchMe1, DontCatchMe2):
# Handle err

HTH,
~Simon
 
S

Simon Forman

Simon said:
try:
# Do some stuff
except Exception, err:
if err not in (DontCatchMe1, DontCatchMe2):
# Handle err

HTH,
~Simon

Dang! not only did somebody else beat me to it, but my code is wrong
and theirs correct.

Sorry,
~Simon
 
G

Georg Brandl

Carl said:
Hrmms, well, here's an interesting situation. So say we wanna catch
most exceptions but we don't necessarily know what they are going to
be. For example, I have a framework that executes modules (python
functions), the framework wraps each function execution in a try/except
block in order to compensate for what *might* happen. Upon coding the
framework I really have no idea what types of problems these modules
might have but I want to catch these errors so that I can clean up and
exit gracefully, not only that but I want to dump the exception to log
files so that we can attempt to fix it. So, I have the option of
catching all standard exceptions and not list the ones I know I don't
want to catch. But what about user defined exceptions? Do I then have
to enforce policies on the system stating what types of exceptions can
be raised?

Is there a way in python to say, "hey, catch everything but these two"?

Yes:

try:
...some code...
except (AttributeError, TypeError):
raise
except Exception, e:
handle all other exceptions

is the most Pythonic solution.

Georg
 
A

Ant

Dang! not only did somebody else beat me to it, but my code is wrong
and theirs correct.

Ignoring the fact you haven't re-raised the exception (as we can ignore
the fact mine doesn't handle the others ;-) ), it does show a different
valid approach: mine has an advantage if the exceptions you don't want
to handle inherit from a small number of base classes; yours has the
advantage if there are a large number of unrelated exceptions that need
ignoring.
 
G

Georg Brandl

Ant said:
... raise AttributeError
... except Exception, ex:
... if isinstance(ex, AttributeError):
... print "Won't catch it!"
... raise ex
...

Won't catch it!
Traceback (most recent call last):
File "<stdin>", line 7, in ?
AttributeError

Or that sort of thing.

To just reraise an exception, use a bare "raise".

Georg
 
G

Georg Brandl

Ant said:
Ignoring the fact you haven't re-raised the exception (as we can ignore
the fact mine doesn't handle the others ;-) ), it does show a different
valid approach: mine has an advantage if the exceptions you don't want
to handle inherit from a small number of base classes; yours has the
advantage if there are a large number of unrelated exceptions that need
ignoring.

His code is wrong since "err" is not the exception class but an instance.
"if type(err) ..." would be correct but unpythonic.

Georg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top