How can I pickle a dynamically created nested class in python?

prinzdezibel picture prinzdezibel · Dec 22, 2009 · Viewed 21.1k times · Source

I have a nested class:

class WidgetType(object):
    
    class FloatType(object):
        pass
    
    class TextType(object):
        pass

.. and an object that refers the nested class type (not an instance of it) like this

class ObjectToPickle(object):
     def __init__(self):
         self.type = WidgetType.TextType

Trying to serialize an instance of the ObjectToPickle class results in:

PicklingError: Can't pickle <class 'setmanager.app.site.widget_data_types.TextType'>

Is there a way to pickle nested classes in python?

Answer

Nadia Alramli picture Nadia Alramli · Dec 22, 2009

The pickle module is trying to get the TextType class from the module. But since the class is nested it doesn't work. jasonjs's suggestion will work. Here are the lines in pickle.py responsible for the error message:

    try:
        __import__(module)
        mod = sys.modules[module]
        klass = getattr(mod, name)
    except (ImportError, KeyError, AttributeError):
        raise PicklingError(
            "Can't pickle %r: it's not found as %s.%s" %
            (obj, module, name))

klass = getattr(mod, name) will not work in the nested class case of course. To demonstrate what is going on try to add these lines before pickling the instance:

import sys
setattr(sys.modules[__name__], 'TextType', WidgetType.TextType)

This code adds TextType as an attribute to the module. The pickling should work just fine. I don't advice you to use this hack though.