101 101 - 6 months ago 22
Python Question

How to robustly check a Python property exists?

Given the following class (with a buggy property) then what is the best foolproof way of checking that the

bar
property exists?

class Foo(object):
@property
def bar(self):
raise AttributeError('unforeseen attribute error!')


Both
hasattr
and
getattr
fail and only
dir
works:

foo = Foo()

print hasattr(foo, 'bar')
# False

try:
getattr(foo, 'bar')
print True
except AttributeError as e:
print False
# False

print 'bar' in dir(foo)
# True


The best all round solution I can think of is:

def robust_hasattr(obj, attr):
return hasattr(obj, attr) or attr in dir(obj)


Is there a better way?

Answer

If you have a buggy property, fix the bug. If raising AttributeError is a bug, then make the property not do that. Raising that exception is the way to signal that you should not be using that attribute.

Using dir() can be a work-around, but it is not foolproof, as dir() is a debugging aid that can both omit information and can be overridden by the object.__dir__ hook (giving your code another vector to introduce bugs). Then there is the possibility of a buggy object.__getattr__ hook, a buggy object.__getattribute__ hook, or even descriptors on the metaclass, all of which would not be detectable by using dir().

Since you are specifically looking for a property, look for the same attribute on the class of your object:

hasattr(foo, 'bar') or isinstance(getattr(type(foo), 'bar', None), property)

For your specific case, the above returns True:

>>> class Foo(object):
...     @property
...     def bar(self):
...         raise AttributeError('unforeseen attribute error!')
...
>>> foo = Foo()
>>> hasattr(foo, 'bar') or isinstance(getattr(type(foo), 'bar', None), property)
True

because there indeed is such a property object on the class.

Comments