我想序列化机器A并在机器B上反序列化python lambda。这有几个明显的问题:
因此,我的问题:
答案 0 :(得分:19)
令人惊讶的是,检查lambda是否在没有关联闭包的情况下工作实际上相当容易。根据{{3}},您只需查看func_closure
属性:
>>> 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 >>>
然后序列化+加载lambda非常简单:
>>> 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
值得一看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.
请注意,您还可以提供闭包...这意味着您甚至可以序列化旧函数的闭包,然后在另一端加载它:)
答案 1 :(得分:4)
我不确定你想做什么,但你可以试试dill。 Dill可以序列化和反序列化lambdas,我相信也适用于闭包内的lambdas。 pickle API是它的API的一个子集。要使用它,只需“将莳萝作为泡菜进口”,然后进行商业酸洗。
>>> import dill
>>> testme = lambda x: lambda y:x
>>> _testme = dill.loads(dill.dumps(testme))
>>> testme
<function <lambda> at 0x1d92530>
>>> _testme
<function <lambda> at 0x1d924f0>
>>>
>>> def complicated(a,b):
... def nested(x):
... return testme(x)(a) * b
... return nested
...
>>> _complicated = dill.loads(dill.dumps(complicated))
>>> complicated
<function complicated at 0x1d925b0>
>>> _complicated
<function complicated at 0x1d92570>
Dill将它的类型注册到pickle
注册表中,所以如果你有一些黑盒子代码使用pickle
并且你无法真正编辑它,那么只需导入dill就可以神奇地使它无需工作monkeypatching第三方代码。或者,如果您希望整个解释器会话通过线路发送为“python图像”,莳萝也可以这样做。
>>> # continuing from above
>>> dill.dump_session('foobar.pkl')
>>>
>>> ^D
dude@sakurai>$ python
Python 2.7.5 (default, Sep 30 2013, 20:15:49)
[GCC 4.2.1 (Apple Inc. build 5566)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> dill.load_session('foobar.pkl')
>>> testme(4)
<function <lambda> at 0x1d924b0>
>>> testme(4)(5)
4
>>> dill.source.getsource(testme)
'testme = lambda x: lambda y:x\n'
您可以轻松地将图像通过ssh发送到另一台计算机,并从那里开始,只要有pickle的版本兼容性以及有关python更改和正在安装的内容的常见警告。如图所示,您还可以提取在上一个会话中定义的lambda源。
Dill还有some good tools帮助您了解代码失败时导致酸洗失败的原因。