Reputation: 81
I'm trying to implement classes for which redis actually holds the attributes, but the user of the class is not aware of this (ie. object persistence across multiple clients). I know there are a few libs that wrap redis for python but none do exactly this in this simple way (but please correct me if I'm wrong on this!)
I've successfully implemented automatic redis storage of attributes but I can't seem to get retrieval to work using __getattribute__
without infinite recursion blowing it up. I think I am being careful about using object.__getattribute__
etc. but obviously I must be missing something:
class redisStored(object):
global redis
# A class method to implement object retrieval from redis
# Call <Classname>.load(<id>) to create a new instance which exists in redis
@classmethod
def load(cls,id):
# Create the object
obj = cls.__new__(cls)
# Set id without calling obj's __setattr__
object.__setattr__(obj,'id',int(id))
# Return the object we created
return obj
def __str__(self):
# Return "<ClassName>:<id>" to differentiate ids in redis
# You can use this to say redis.hgetall(g) where g is the instance
return "%s:%s" % (self.__class__.__name__, str(object.__getattribute__(self,'id')))
# self.id here ^ would cause infinite recursion
# This works fine
def __setattr__(self,name,value):
redis.hset(self,name,value)
return object.__setattr__(self,name,value)
# This blows up with infinite recursion, WHY??
def __getattribute__(self,name):
_val = redis.hget(self,name)
if not _val:
return object.__getattribute__(self,name)
else:
return _val
If I trace this it blows up inside _val = redis.hget(self,name)
but I can't figure out why. Thanks for any help!
Upvotes: 3
Views: 440
Reputation: 186
You should be very carefull with __getattribute__
overloading.
A side effect is that accessing self.__class__
calls __getattribute__
and creates a dummy redis query.
As you are using new-style classes you may want to use __getattr__
instead and avoid infinite recursion problem, although if you use __getattr__
you will return object attribute prior to redis value if this attribute already exists in your instance.
Anyway your object is kind-of immutable as long as you overloaded __setattribute__
method so this is not a big issue.
Please refer to this SO response for a more detailed difference between __getattr__
and __getattribute__
: Difference between __getattr__ vs __getattribute__
Upvotes: 2