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

getattr() woes

P: n/a
Hello

I've found out about a fundamental problem of attribute lookup, the
hard way.

asyncore.py uses the following code:

class dispatcher:
# ...
def __getattr__(self, attr):
return getattr(self.socket, attr)

Now suppose that I'm asking for some attribute not provided by
dispatcher: The lookup mechanism will apparently try to find it
directly and fail, generating an AttributeError; next it will call
__getattr__ to find the attribute. So far, no problems.

But I used a property much like this:
import asyncore
class Peer(asyncore.dispatcher): .... def _get_foo(self):
.... # caused by a bug, several stack levels deeper
.... raise AttributeError('hidden!')
.... foo = property(_get_foo)
....

and as the error message suggests, the original AttributeError is
hidden by the lookup mechanism:
Peer().foo

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/lib/python2.4/asyncore.py", line 366, in __getattr__
return getattr(self.socket, attr)
AttributeError: 'NoneType' object has no attribute 'foo'

Is there anything that can be done about this? If there are no better
solutions, perhaps the documentation for property() could point out
this pitfall?

- Thomas

--
If you want to reply by mail, substitute my first and last name for
'foo' and 'bar', respectively, and remove '.invalid'.
Jul 18 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
In article <87************@thomas.local>,
Thomas Rast <fo*****@freesurf.ch.invalid> wrote:

I've found out about a fundamental problem of attribute lookup, the
hard way.
Maybe.
asyncore.py uses the following code:

class dispatcher:
# ...
def __getattr__(self, attr):
return getattr(self.socket, attr)

Now suppose that I'm asking for some attribute not provided by
dispatcher: The lookup mechanism will apparently try to find it
directly and fail, generating an AttributeError; next it will call
__getattr__ to find the attribute. So far, no problems.

But I used a property much like this:
import asyncore
class Peer(asyncore.dispatcher):

... def _get_foo(self):
... # caused by a bug, several stack levels deeper
... raise AttributeError('hidden!')
... foo = property(_get_foo)
...


You're not supposed to use properties with classic classes.
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"19. A language that doesn't affect the way you think about programming,
is not worth knowing." --Alan Perlis
Jul 18 '05 #2

P: n/a
aa**@pythoncraft.com (Aahz) writes:
In article <87************@thomas.local>,
Thomas Rast <fo*****@freesurf.ch.invalid> wrote:

class dispatcher:
# ...
def __getattr__(self, attr):
return getattr(self.socket, attr)
> import asyncore
> class Peer(asyncore.dispatcher):

... def _get_foo(self):
... # caused by a bug, several stack levels deeper
... raise AttributeError('hidden!')
... foo = property(_get_foo)
...


You're not supposed to use properties with classic classes.


Even if dispatcher was a new-style class, you still get the same
behaviour (or misbehaviour) -- Peer().foo still raises AttributeError
with the wrong message.

A simple workaround is to put a try ... except AttributeError block in
his _get_foo(), which would re-raise with a different error that
wouldn't be caught by getattr. You could even write a property
replacement for that:
class HiddenAttributeError(Exception): .... pass def robustprop(fget):

.... def wrapped_fget(self):
.... try:
.... return fget(self)
.... except AttributeError, e:
.... raise HiddenAttributeError(*e.args)
.... return property(fget=wrapped_fget)

Ideally, I think the better way is if getattr, when raising
AttributeError, somehow reused the old traceback (which would point
out the original problem). I don't know how to do that, though.

--
|>|\/|<
/--------------------------------------------------------------------------\
|David M. Cooke
|cookedm(at)physics(dot)mcmaster(dot)ca
Jul 18 '05 #3

P: n/a
David M. Cooke wrote:
Ideally, I think the better way is if getattr, when raising
AttributeError, somehow reused the old traceback (which would point
out the original problem). I don't know how to do that, though.


Maybe a solution could be to put the attribute name in the
AttributeError exception object, and use it in getattr; if the name
doesn't match, the exception is re-raised. It's still not flawless, but
would reduce risk of errors.

Nicolas
Jul 18 '05 #4

P: n/a
Thomas Rast wrote:
I've found out about a fundamental problem of attribute lookup, the
hard way... Is there anything that can be done about this?


It seems to me that the main problem is you're raising an AttributeError
when an attribute is private. AttributeError is only raised when an
attribute is not found. If you found it, but it's private, that's a
different problem. Try raising a custom exception instead of an
AttributeError, if you can.

Jul 18 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.