Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I can "pickle local objects" if I use a derived class?

The pickle reference states that the set of objects which can be pickled is rather limited. Indeed, I have a function which returns a dinamically-generated class, and I found I can't pickle instances of that class:

>>> import pickle >>> def f(): ...     class A: pass ...     return A ...  >>> LocalA = f() >>> la = LocalA() >>> with open('testing.pickle', 'wb') as f: ...     pickle.dump(la, f, pickle.HIGHEST_PROTOCOL) ...  Traceback (most recent call last):   File "<stdin>", line 2, in <module> AttributeError: Can't pickle local object 'f.<locals>.A' 

Such objects are too complicated for pickle. Ok. Now, what's magic is that, if I try to pickle a similar object, but of a derived class, it works!

>>> class DerivedA(LocalA): pass ...  >>> da = DerivedA() >>> with open('testing.pickle', 'wb') as f: ...     pickle.dump(da, f, pickle.HIGHEST_PROTOCOL) ... >>> 

What's happening here? If this is so easy, why doesn't pickle use this workaround to implement a dump method that allows "local objects" to be pickled?

like image 455
fonini Avatar asked May 03 '16 02:05

fonini


People also ask

Which functions Cannot be pickled?

11. Which of the following cannot be pickled? Explanation: Functions which are defined at the top level of a module with lambda cannot be pickled.

What Cannot be pickled in Python?

With pickle protocol v1, you cannot pickle open file objects, network connections, or database connections.

Can any Python object be pickled?

Python pickle module is used for serializing and de-serializing a Python object structure. Any object in Python can be pickled so that it can be saved on disk. What pickle does is that it “serializes” the object first before writing it to file. Pickling is a way to convert a python object (list, dict, etc.)

Is pickling used for object serialization?

Pickle in Python is primarily used in serializing and deserializing a Python object structure. In other words, it's the process of converting a Python object into a byte stream to store it in a file/database, maintain program state across sessions, or transport data over the network.


1 Answers

I think you did not read the reference you cite carefully. The reference also clearly states that only the following objects are pickleable:

  • functions defined at the top level of a module (using def, not >lambda)
  • built-in functions defined at the top level of a module
  • classes that are defined at the top level of a module

Your example

>>> def f(): ...     class A: pass ...     return A 

does not define a class at the top level of a module, it defines a class within the scope of f(). pickle works on global classes, not local classes. This automatically fails the pickleable test.

DerivedA is a global class, so all is well.

As for why only top-level (global to you) classes and functions can't be pickled, the reference answers that question as well (bold mine):

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.

So there you have it. pickle only serialises objects by name reference, not by the raw instructions contained within the object. This is because pickle's job is to serialise object hierarchy, and nothing else.

like image 193
Akshat Mahajan Avatar answered Sep 19 '22 18:09

Akshat Mahajan