By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,544 Members | 1,470 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,544 IT Pros & Developers. It's quick & easy.

Abuse of the object-nature of functions?

P: n/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?

Jul 11 '06 #1
Share this Question
Share on Google+
15 Replies


P: n/a
"Ant" <an****@gmail.comwrote:
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>

Jul 11 '06 #2

P: n/a
Sybren Stuvel wrote:
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.
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>

Jul 11 '06 #3

P: n/a
Fredrik Lundh wrote:
Sybren Stuvel wrote:
>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.

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
Jul 11 '06 #4

P: n/a
Peter Otten wrote:
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>

Jul 11 '06 #5

P: n/a
Ant
Sybren wrote:
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.

Fredrik Lundh wrote:
Peter Otten wrote:
assertion = getattr(callable, "is_assertion", False)
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:
>>def assn_or_other(data):
.... return False
....
>># I want x to be treated as normal.
.... x = assn_or_other
>>>
# I want y to be an assertion
.... y = assn_or_other
>>y.is_assertion = True
x.is_assertion
True

Jul 11 '06 #6

P: n/a
Sybren Stuvel wrote:
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.

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
cv*********@mvista.com
Build and Release
MontaVista Software

Jul 11 '06 #7

P: n/a
Carl J. Van Arsdall wrote:
Sybren Stuvel wrote:
>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.


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...)

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Jul 11 '06 #8

P: n/a
Bruno Desthuilliers wrote:
Carl J. Van Arsdall wrote:
>Sybren Stuvel wrote:

>>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.
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...)

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
cv*********@mvista.com
Build and Release
MontaVista Software

Jul 11 '06 #9

P: n/a
Ant
Is there a way in python to say, "hey, catch everything but these two"?
>>try:
.... 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.

Jul 11 '06 #10

P: n/a
Carl J. Van Arsdall wrote:
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
cv*********@mvista.com
Build and Release
MontaVista Software

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

HTH,
~Simon

Jul 11 '06 #11

P: n/a

Simon Forman wrote:
Carl J. Van Arsdall wrote:
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
cv*********@mvista.com
Build and Release
MontaVista Software


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

Jul 11 '06 #12

P: n/a
Carl J. Van Arsdall wrote:
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
Jul 11 '06 #13

P: n/a
Ant
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.
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.

Jul 11 '06 #14

P: n/a
Ant wrote:
>Is there a way in python to say, "hey, catch everything but these two"?
>>>try:
... 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
Jul 11 '06 #15

P: n/a
Ant wrote:
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.

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
Jul 11 '06 #16

This discussion thread is closed

Replies have been disabled for this discussion.