Search code examples
pythonclasspickledefinition

How can I pickle a class definition?


I am having troubles pickling a class importing a class from another module.

Immagine I have a file classA.py with the definition of a class A:

class A:
    def execute(self):
        print('Hello from class A!')

Then I have another file classB.py:

import dill
import classA

class B:
    def __init__(self):
        self.a = classA.A()

    def execute(self):
        self.a.execute()
        print('Hello from class B!')


b = B()

with open('/file/path', 'wb') as f:
    dill.dump(b, f)

If then I try to unpickle the created file from a different directory with:

with open('file/path', 'rb') as f:
    b = dill.load(f)

I get the error:

ModuleNotFoundError: No module named 'classB'

It works of course in the same folder in which I have the files classA.py and classB.py because the interpreter can find the definition of the two classes.

So I guess I have to somehow bring the definition of the classes into the pickle file. How can I do that?

Thank you Stefano


Solution

  • It works of course in the same folder in which I have the files classA.py and classB.py because the interpreter can find the definition of the two classes. So I guess I have to somehow bring the definition of the classes into the pickle file. How can I do that?

    That's not how it works. You don't "bring the definition of the classes into the pickle file" - which would make no sense since only the class qualified name is pickled (qualified name => packagename.modulename.classname)

    Instead, you have to make sure the modules where the classes are defined are importable when unpickling - "importable" meaning that the package or module's parent folder path is in your sys.path. You can do this in a few way (using PYTHONPATH environment variable, messing with sys.path directly in your code - which is often a bad idea and sometimes the proper solution -, installing your module in virtualenv and activating this virtualenv, etc)

    NB: The current working directory is always first in your sys.path which is why "It works of course in the same folder".