(begginer) issue with pickling class objects
Steve Holden
sholden at holdenweb.com
Sun Apr 8 17:45:01 EDT 2001
"François Granger" <francois.granger at free.fr> wrote ...
> I send below a simplified version of the code I am writing. When I run
> it I get the following error message:
> 'Failed to import class B from module __main__'
> I tired an alternative wich is commented out (line 44-51 , 61 and 65)
> but the error message is similar with a reference to class A.
>
The problem here is that the objects you are pickling are instances of
classes defined in your main module. When you call pickle.load() Python
tries to re-import the class definition from its original module, but it
cannot. The doumentation specifically states that the class of pickled
objects must be importable, and the easiest way to arrange that is to put
the class definitions in a separate module.
> I am guessing that this is an issue with namespace that I don't really
> understand.
>
It isn't terribly explicit in the documentation, so it isn't surprising. If
you have a copy of Hammond & Robinson's "Win32 Programming in Python" then
there's a good explanation in that book.
> On a similar track, I would be happy to see a more general algorithm to
> implement persistence of complexe objects between runs.
>
I believe Andrew Kuchling's ZODB implementation, as used in ZOPE, might be
of interest to you. Andrew recently broke out a separate implementation,
which I understand will be sync'ed with ZOPE for releases, but now also has
an independent existence.
Take a look at
http://zodb.sourceforge.net/
and the linked documentation to see if it better meets your needs.
There is also the issue of your using class variables to identify instances.
In the __init__() method for B you appear to be generating a dictionary of A
instances for input and output, then iterating over the keys to gain access
to the instances.
Unless you have more devious later applications in mind, it would seem more
natural to simply generate a list of instances. I have recast your code into
two modules, using lists rather than dictionaries, and added a __repr__
method to the B class to allow for easy verification. Seems to work OK. Hope
this helps.
regards
Steve
=============main.py=================
# python
"""
Simple test of pickling complex objects
"""
import pickle
import neurons
if __name__ == '__main__':
inp = 10
out = 10
N = neurons.B(inp, out)
for i in range(5):
N.transmit()
fp = open('neuronet.txt', 'wb')
#N.save_NN(fp)
pickle.dump(N, fp)
fp.close()
print "AFTER PICKLING:", N
N = None # ensure isolation!
fp = open('neuronet.txt', 'rb')
#N.load_NN(fp)
N = pickle.load(fp)
fp.close()
print "RELOADED PICKLE:", N
pass
=============neurons.py=================
class A:
"""
"""
id = 0
def __init__(self):
A.id += 1
self.value = 0.0
self.id = A.id
def __repr__(self):
return str(self.__dict__) + '\n'
def activate(self):
self.value += 1.0
class B:
"""
"""
def __init__(self, ninput = 10, noutput = 10):
self.ninput = ninput
self.noutput = noutput
self.input = []
for i in range(self.ninput):
self.input.append(A())
self.output = []
for i in range(self.noutput):
self.output.append(A())
def transmit(self):
for i in self.input:
i.activate()
for i in self.output:
i.activate()
def __repr__(self):
result = "NEURON STATE:\n"
for i in self.input:
result += "Input: "+`i`
for i in self.output:
result += "Output:" + `i`
return result
"""
def save_NN(self, fp):
pickle.dump((self.input, self.output), fp)
pass
def load_NN(self, fp):
#set neuron.id to max id ?
self.input, self.layer, self.output = pickle.load(fp)
pass
"""
=============code ends=================
More information about the Python-list
mailing list