• 12

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191


File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

Pickling dynamically generated classes?

I'm using type() to dynamically generate classes that will ultimately be pickled. The problem is that the un-pickling process needs the definition of the class in order to re-construct the object that has been pickled.

This is where I'm stuck. I don't know how to somehow provide the unpickler a way to generate an instance from a class that was dynamically generated.

Any hints appreciated.


Here's an example of the problem:

    >>> class Foo(object):
    ...     pass
    >>> g=type('Goo',(Foo,),{'run':lambda self,x: 2*x } )()
    >>> cPickle.dumps(g)

    PicklingError: Can't pickle <class '__main__.Goo'>: attribute lookup __main__.Goo failed

This evidently works, but only from dynamic classes created from a pickle-able base class (with find-able module definition):

import cPickle

class Foo(object): pass

def dynamic(): return type('Goo',(Foo,),{'run':lambda self,x: 2*x } )()

g=type('Goo',(Foo,),{'run':lambda self,x: 2*x , '__reduce__': lambda self: (dynamic,tuple()) } )()

gg=cPickle.loads ( cPickle.dumps(g) )
print gg.run(10)
    • Avoid using pickle... it's slow, brittle, and can open up arbitrary code execution vulnerabilities. Instead, use a serialization format like JSON or YAML.
    • @ColinDunklau i think if you use python's multiprocessing module and shared memory, then your forced to ensure objects your sharing can be pickled. The mp modules uses pickling to achieve shared memory.

You can assign a global name to your dynamically generated class to make it picklable.

>>> class Foo(object):
...     pass
>>> class_name = 'Goo'
>>> my_class = type(class_name, (Foo, ), {'run': lambda self, x: 2*x })
>>> globals()[class_name] = my_class
>>> g = my_class()
>>> pickle.dumps(g)

Of course, you need to make sure that the names of your classes are unique.

  • 4
Reply Report

One idea would be to pickle a tuple with:

  1. The name of the dynamic class
  2. The subclass tuple (possibly in string form from repr())
  3. The class dictionary
  4. The actual instance

This would allow you to pickle a class and then reconstruct it later using type() and subclassing Unpickler.

  • 2
Reply Report

For non-dynamic classes, python's pickling mechanism records the module and class name as strings. At unpickle time, it automatically loads the class object from that module.

As mentioned in the original post, the problem here is that for dynamic classes, the class definition itself is not pickled by the default pickler. Since dynamic classes don't exist in a module's source file, unpickling a dynamic class generally won't work.

The trickiest part of pickling the class itself is storing the methods' bytecode. Buried in PiCloud, there's an enhanced pickler under the hood that can pickle dynamic functions you could probably use or extend it to handle your objects.

  • 1
Reply Report

Trending Tags