Serializing and deserializing lambda functions

Lambda and the module marshal

The first investigation is to check whether we can serialize and deserialize lambda functions. I basically took the example from here: http://stackoverflow.com/questions/11878300/serializing-and-deserializing-lambdas


In [3]:
import marshal, types

# a simple square function with a lambda function
square = lambda value: value**2
print(square, square(32))

# serializing the lambda function
square_code_serialized = marshal.dumps(square.func_code)
print(square_code_serialized)

# desersializing the lambda function
square_reloaded = types.FunctionType(marshal.loads(square_code_serialized), globals())
print(square_reloaded, square_reloaded(32))


(<function <lambda> at 0x7f7cd8177140>, 1024)
cCs|dS(Ni((tvalue((s<ipython-input-3-7cb759660c89>t<lambda>s
(<function <lambda> at 0x7f7cd8177398>, 1024)

Lambda and JSON

The next step is to check whether we can serialize and deserialize it via JSON. It's to mention that we here miss the automatic conversion from/to lambda so we provided it directly otherwise it wouldn't work (You cannot do a "json.dumps({'code': lambda value: value**2})")


In [11]:
import json
json_serialized = json.dumps({'code': square_code_serialized})
print(json_serialized)

json_deserialized = json.loads(json_serialized)
json_deserialized['code'] = types.FunctionType(marshal.loads(json_deserialized['code']), globals())
print(json_deserialized, json_deserialized['code'](32))


{"code": "c\u0001\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0002\u0000\u0000\u0000C\u0000\u0000\u0000s\b\u0000\u0000\u0000|\u0000\u0000d\u0001\u0000\u0013S(\u0002\u0000\u0000\u0000Ni\u0002\u0000\u0000\u0000(\u0000\u0000\u0000\u0000(\u0001\u0000\u0000\u0000t\u0005\u0000\u0000\u0000value(\u0000\u0000\u0000\u0000(\u0000\u0000\u0000\u0000s\u001e\u0000\u0000\u0000<ipython-input-3-7cb759660c89>t\b\u0000\u0000\u0000<lambda>\u0004\u0000\u0000\u0000s\u0000\u0000\u0000\u0000"}
({u'code': <function <lambda> at 0x7f7cd8177320>}, 1024)

JSON Encoder and JSON Decoder

Basicall I'm quite comfortable with the encoder class except that I miss a is_lambda function as builtin. Unfortunately the decoder class is not as straight forward. With a hook function I got it also more by trying then by refering to a documentation. A working example but not yet convinced to put it into the concept-py code base.


In [47]:
class LambdaEncoder(json.JSONEncoder):
     def default(self, o):
        # TODO: missing a is_lambda function ...
        LAMBDA = lambda:0
        if isinstance(o, type(LAMBDA)):
            return marshal.dumps(o.func_code)
        return json.JSONEncoder.default(self, o)

def lambda_decoder(o):
    """
    a bit tricky since I'm relying on what I have seen when dumping
    the serialized lambda code. But since I have no better solution ...
    """"
    for pos, entry in enumerate(o):
        key, value = entry[0], entry[1]
        if str(value).find("lambda") >= 0:
            o[pos] = (key, types.FunctionType(marshal.loads(value), globals()))
    return dict(o)

# TODO: using a class for encoding and a function for decoding ... should be harmonized somehow.
json_serialized = json.dumps({'code': lambda value: value**2, 'value': 12334},cls=LambdaEncoder)
json_deserialized = json.loads(json_serialized, object_pairs_hook=lambda_decoder)
print(json_deserialized['code'](32))


{u'code': <function <lambda> at 0x7f7cd809e320>, u'value': 12334}
1024

Conclusion until now

  • implementing a is_lambda for function concept.py (no problem)
  • implementing an encode_lambda function (problem)
  • implementing a decode_lambda function (problem)

The problems mentioned are Python versions and how they handle internals like square.func_code which does not exist in Python 3.x


In [ ]: