简体   繁体   中英

pickle.dump error for object defined by class

I have object defined as A = Object() where I specified class Object(): pass I proceeded to construct attributes, Ab, Ac, etc. Most are lists, some of whose items are lists. I wrote:

  outFile = file('A.obj','wb')
  pickle.dump(A,outFile)
  outFile.close()

I got error:

PicklingError: Can't pickle <class '__main__.Object'>: it's not found as __main__.Object

My goal is to be able to dump (and later load) objects.

The error is quite clear. You did something like(or equivalent to) the following:

>>> import pickle
>>> class Object(object): pass
... 
>>> A = Object
>>> del Object
>>> pickle.dumps(A)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/pickle.py", line 1374, in dumps
    Pickler(file, protocol).dump(obj)
  File "/usr/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib/python2.7/pickle.py", line 748, in save_global
    (obj, module, name))
pickle.PicklingError: Can't pickle <class '__main__.Object'>: it's not found as __main__.Object

This is addressed quite clearly by pickle 's documentation:

Note that functions (built-in and user-defined) are pickled by “fully qualified” name reference, not by value . This means that only the function name is pickled, along with the name of the module the function is defined in . Neither the function's code, nor any of its function attributes are pickled. Thus the defining module must be importable in the unpickling environment, and the module must contain the named object, otherwise an exception will be raised.

Similarly, classes are pickled by named reference , so the same restrictions in the unpickling environment apply. Note that none of the class's code or data is pickled

Hence, the name of the class must be available when pickling/unpickling. After doing:

>>> A = Object
>>> del Object

if you try to pickle A , the pickle module will check whether it can access the class. But since A.__name__ is Object it cannot find it and fails to pickle it.


Note that the same applies to instances of user-defined classes:

Similarly, when class instances are pickled, their class's code and data are not pickled along with them. Only the instance data are pickled . This is done on purpose, so you can fix bugs in a class or add methods to the class and still load objects that were created with an earlier version of the class. If you plan to have long-lived objects that will see many versions of a class, it may be worthwhile to put a version number in the objects so that suitable conversions can be made by the class's __setstate__() method.

So... say you were building something like this... which builds an instance of a class inside a factory method. Then you'd get the error you reporting. Look at the traceback... what pickle's trying to do is use pickle.save_global to serialize your class. Being built inside of a function, but in __main__ , the class actually gets named __main___.Object ... and there is no __main__.Object class... it's nested inside the object_factory namespace. In python, the factory method is used a lot to dynamically build classes, instances, functions, and other objects. If you are using a factory method, you could instead build a factory method inside another class instead of a function... and you'd have a better chance at a pickler being able to serialize your instance of the Object class than you do now.

>>> def object_factory(a,b):
...   c = a+b
...   class Object(object):
...     d = 1
...     e = [c, d, [1,2,3]]
...     def foo(self, x):
...       return (self.d * c) + (x * Object.e)
...   return Object()
... 
>>> A = object_factory([4,5],[6,7])
>>> A
<__main__.Object object at 0x973030>
>>> A.d
1
>>> A.e
[[4, 5, 6, 7], 1, [1, 2, 3]]
>>> A.foo(1)
[4, 5, 6, 7, [4, 5, 6, 7], 1, [1, 2, 3]]
>>> 
>>> _A = pickle.dumps(A)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 1366, in dumps
    Pickler(file, protocol).dump(obj)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 224, in dump
    self.save(obj)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 401, in save_reduce
    save(args)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 562, in save_tuple
    save(element)
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 753, in save_global
    (obj, module, name))
pickle.PicklingError: Can't pickle <class '__main__.Object'>: it's not the same object as __main__.Object

It would help to have your code posted, or at least some toy code that demonstrates your problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM