【问题标题】:Problematic function pickling有问题的功能酸洗
【发布时间】:2013-06-06 08:15:52
【问题描述】:

在一个模块中,我有一个类,它需要一个函数作为其参数之一:

class Foo():
    def __init__(self, fun):
        self.fun = fun

    def call_fun(self, arg):
        self.fun(arg)

在另一个模块中,我有几个函数,我最终在创建此类的对象时将它们作为参数传递。我正在通过以下方式绑定值以轻松自定义功能:

def sample_function(value):
    return (lambda arg: arg.effect(value))

初始化 Foo 对象时,我传递如下值:

foo = Foo(sample_function(5))

稍后,我想搁置一些对象,包括 Foo 对象,这很快就证明是不可能的(因为 pickle 模块返回 'TypeError: can't pickle function objects')。我完全了解 pickle 的序列化机制的局限性,并且我意识到为什么无法对这些对象进行酸洗。相反,我想重新设计我的课程,或使用其他序列化方式。如何重新设计它以便我可以搁置 Foo 对象,同时保留它们的属性?

【问题讨论】:

  • 为了清楚起见,您是想在腌制 Foo 时腌制您的函数,还是只需要一种方法来腌制没有该功能的 Foo,同时在取回该函数后仍然能够重新加载该函数?
  • 老实说,无论哪种方式我都可以。

标签: python pickle shelve


【解决方案1】:

您的代码的主要问题是“sample_function”中的关闭。如果没有闭包,可以使用 marshal 和 types 模块来完成,这里有一些例子:

import pickle
import marshal
import types

class Foo():
    def __init__(self, fun):
        self.fun = fun

    def call_fun(self, arg):
        self.fun(arg)

    def save(self, f):
        saved = self.fun
        self.fun = marshal.dumps(self.fun.func_code)
        pickle.dump(self, f)
        self.fun = saved

    @staticmethod
    def load(f):
        foo = pickle.load(f)
        foo.fun = types.FunctionType(marshal.loads(foo.fun), globals())
        return foo

def sample_function(arg):
    arg.effect(4)

class Arg():
    def effect(self, value):
        print "ok: " + str(value)

有了这个类和函数,你可以保存:

foo = Foo(sample_function)

f = open('foo', 'w')
foo.save(f)
f.close()

并加载:

f = open('foo', 'r')
foo = Foo.load(f)
f.close()

这个想法是在酸洗之前编组“乐趣”(并恢复它,因此类不会被破坏)并在加载时将编组的代码作为函数加载。

但这不适用于闭包(因为闭包需要来自调用函数的变量)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-27
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多