Python序列化词法闭包?

2024-06-16 10:07:17 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有一种方法可以使用标准库序列化Python中的词法闭包?pickle和marshal似乎不能处理词汇闭包。我真的不关心二进制与字符串序列化的细节,它只需要工作。例如:

def foo(bar, baz) :
    def closure(waldo) :
        return baz * waldo
    return closure

我只希望能够将闭包实例转储到一个文件中并读回它们。在

编辑: 解决这个问题的一个相对明显的方法是使用一些反射黑客将词汇闭包转换为类对象,反之亦然。然后可以转换为类、序列化、取消序列化、转换回闭包。如果Python是duck类型的,那么如果重载类的函数调用运算符使其看起来像函数,那么甚至不需要将它转换回闭包,并且使用它的代码也不知道区别。如果有Python反射API专家,请大声说出来。在


Tags: 方法字符串标准return序列化def二进制baz
3条回答

如果您只使用一个带有__call__方法的类,那么它应该可以顺利地与pickle一起工作。在

class foo(object):
    def __init__(self, bar, baz):
        self.baz = baz
    def __call__(self,waldo):
        return self.baz * waldo

另一方面,由于pickle处理类和实例的方式,将闭包转换为在运行时创建的新类的实例的黑客行为是行不通的。pickle不存储类;只存储模块名和类名。当读回一个实例或类时,它尝试导入模块并在其中找到所需的类。如果你使用了一个动态创建的类,那你就倒霉了。在

是的!我明白了(至少我认为是这样的)——这是一个更普遍的函数酸洗问题。Python太棒了:),我通过dir()函数和几个web搜索找到了它的大部分内容。很高兴解决了这个问题,我也需要它。在

我还没有做过很多测试来测试这种代码的健壮性(嵌套的fcn等等),如果有人能找到如何钩住Python以便函数可以自动地被pickle(例如,它们有时可能是闭包参数)那就更好了。在

Cython模块泡菜_fcn.pyx公司在

# -*- coding: utf-8 -*-

cdef extern from "Python.h":
    object PyCell_New(object value)

def recreate_cell(value):
    return PyCell_New(value)

Python文件

^{pr2}$

干杯,
尼古拉斯

编辑-对于真实世界的案例,需要更强大的全局处理。功能代码.co_names列出全局名称。在

PiCloud发布了一个开源(LGPL)pickler,它可以处理函数闭包和更多有用的东西。它可以独立于他们的云计算基础设施使用——这只是一个普通的泡菜。整个shebang都有文档记录here,您可以通过“pip install cloud”下载代码。不管怎样,它做你想做的。让我们通过酸洗来证明:

import pickle
from StringIO import StringIO

import cloud

# generate a closure
def foo(bar, baz):
    def closure(waldo):
        return baz * waldo
    return closure
closey = foo(3, 5)

# use the picloud pickler to pickle to a string
f = StringIO()
pickler = cloud.serialization.cloudpickle.CloudPickler(f)
pickler.dump(closey)

#rewind the virtual file and reload
f.seek(0)
closey2 = pickle.load(f)

现在我们有了closey,原始闭包,closey2,这是从字符串序列化中恢复的闭包。让我们测试一下

^{pr2}$

很漂亮。这个模块是纯python的,你可以打开它,很容易地看到是什么让魔法起作用。(答案是大量代码。)

相关问题 更多 >