From: Alan K. <sql...@xh...> - 2004-10-15 20:39:34
|
Greetings all, I'm getting to grips with SQLObject at the moment. I like it very much, it is an excellent and pythonic bridge between the object and relational worlds. I'm trying to pickle SQLObjects, so that I can store them in structured documents. As far as I can see, pickles only need to contain the name of the SQLObject class, and the id which uniquely identifies the instance. From what I understand, the id attributes of SQLObjects uniquely identify the object instance in the SQLObject's class/table. This should mean that I could use these ids in references in data stored outside SQLObject, and know that I will get the correct instance when I recreate the SQLObject, through the use of the ClassName.get(id). The same should hold true when I store ids in pickles. If I store and retrieve SQLObjects through the pickle protocol, i.e. by defining the __getstate__ and __setstate__ methods like so class MoSQLObject(SQLObject): def __getstate__(self): return self.id def __setstate__(self, id): return self.__class__.get(id) Then I should get the same SQLObject, i.e. an object with the same id, back from unpickling process. But I'm finding that that isn't working. The object that I get back from the unpickling process seems to be the right SQLObject, but it's missing the id attribute. The following code illustrates the problem. #source -------- import pickle import sqlobject __connection__ = sqlobject.connectionForURI('sqlite:/data/database.db') class PickleableSQLObject(sqlobject.SQLObject): def __getstate__(self): return self.id def __setstate__(self, id): return self.__class__.get(id) class MoSQLObject(PickleableSQLObject): name = sqlobject.StringCol() if __name__ == "__main__": MoSQLObject.createTable(ifNotExists=True) obj = MoSQLObject(name='alan') print "Object is %s" % str(obj) pickled = pickle.dumps(obj) print "Pickled object is %d bytes" % len(pickled) unpickled = pickle.loads(pickled) print "Unpickled object is %s" % str(unpickled) #source -------- The above code outputs the following #output -------- Object is <MoSQLObject 1 name='alan'> Pickled object is 91 bytes Traceback (most recent call last): File "test_sqlobject_pickle.py", line 25, in ? print "Unpickled object is %s" % str(unpickled) File "C:\Python23\Lib\site-packages\sqlobject\main.py", line 1072, in __repr__ return '<%s %r %s>' \ AttributeError: 'MoSQLObject' object has no attribute 'id' #output -------- So it seems the id attribute has gone missing. I have verified that it is there before the SQLObject is returned from __setstate__, but has disappeared by the time it gets returned by pickle.loads(). Which leads me to think one of two things 1. There is some form of clash between the semantics of 'id' attributes in the SQLObject and pickle modules. 2. I have failed to grok SQLObject, and am not using it correctly. Particularly, I may have missed some essential constraints or rules relating to object identity? I'd be grateful if anyone could shed any light. TIA, Alan. |