Persist a class (not an instance)

Phillip J. Eby pje at telecommunity.com
Sat Nov 26 15:47:14 EST 2005


David  Wahler wrote:
> Kent Johnson wrote:
> > Is there a way to persist a class definition (not a class instance,
> > the actual class) so it can be restored later? A naive approach
> > using pickle doesn't work:
> [snip]
> > The idea is to persist classes that are created and modified at runtime.
>
> I couldn't resist the challenge, so I decided to take a crack at it. My
> code is below. (I hope it's OK to post it even though it's a bit on the
> long side.) So far, it seems to work OK; the biggest caveat to be aware
> of is that functions' global context is not preserved.
>
> My approach was to use pickle's __reduce__ protocol to store functions
> and classes. Of course, you can't modify the built-in function and
> classobj types, so I subclassed Pickler to override them. The advantage
> of this is that you don't need an extension to the pickling data
> format, and you can use the standard unpickler. (The custom module
> still needs to have been imported, as it adds the classobj type to
> __builtins__.)
>
> Unfortunately, I'm not sure how to go about making it work for
> new-style classes. It would seem to involve messing with dictproxy and
> descriptor objects, and that's getting me into more unfamiliar
> territory.
>
> I'm sure there's a better way to do this; this seemed like "the
> simplest thing that could possibly work".

This is actually pretty sweet.  It seems to me that you'll be fine with
new-style classes if you just save dict(ob.__dict__) instead of trying
to save __dict__ directly, as that'll get rid of the dictproxy part.
There's no generic way to save descriptors, as far as I know, but you
can always register reducers for specific types, like property, and
user-defined descriptor classes are likely to be picklable anyway.

As for functions' global context, you could look to see if there's a
__name__ present, in which case you can save a reference to that
module's __dict__.  Otherwise, simply pickle the func_globals as-is.
Some folks might just want to do that anyway, if the code isn't
actually being loaded from a module.

Of course, the classic caveat regarding pickles and security applies to
all this.  That is, pickles and security don't mix.  If you want one,
you can't really get the other.  ;-)




More information about the Python-list mailing list