serializing and deserializing lambdas
Question: I would like to serialize on machine A and deserialize on machine B a python
lambda. There are a couple of obvious problems with that:

  * the pickle module does not serialize or deserialize code. It only serializes the names of classes/methods/functions
  * some of the answers I found with google suggest the use of the low-level marshal module to serialize the func_code attribute of the lambda but they fail to describe how one could reconstruct a function object from the deserialized code object
  * marhshal(l.func_code) will not serialize the closure associated with the lambda which leads to the problem of detecting when a given lambda really needs a closure and warning the user that he is trying to serialize a lambda that uses a closure

Hence, my question(s):

  * how would one reconstruct a function from the deserialized (demarshaled) code object ?
  * how would one detect that a given lambda will not work properly without the associated closure ?


Answer: Surprisingly, checking whether a lambda will work without its associated
closure is actually fairly easy. According to the [data model
documentation](http://docs.python.org/release/2.6.2/reference/datamodel.html),
you can just check the `func_closure` attribute:

    
    
    >>> def get_lambdas():
    ...     bar = 42
    ...     return (lambda: 1, lambda: bar)
    ...
    >>> no_vars, vars = get_lambdas()
    >>> print no_vars.func_closure
    None
    >>> print vars.func_closure
    (<cell at 0x1020d3d70: int object at 0x7fc150413708>,)
    >>> print vars.func_closure[0].cell_contents
    42
    >>>
    

Then serializing + loading the lambda is fairly straight forward:

    
    
    >>> import marshal, types
    >>> old = lambda: 42
    >>> old_code_serialized = marshal.dumps(old.func_code)
    >>> new_code = marshal.loads(old_code_serialized)
    >>> new = types.FunctionType(new_code, globals())
    >>> new()
    42
    

It's worth taking a look at the documentation for the `FunctionType`:

    
    
    function(code, globals[, name[, argdefs[, closure]]])
    
    Create a function object from a code object and a dictionary.
    The optional name string overrides the name from the code object.
    The optional argdefs tuple specifies the default argument values.
    The optional closure tuple supplies the bindings for free variables.
    

Notice that you can also supply a closure… Which means you might even be able
to serialize the old function's closure then load it at the other end :)

