简体   繁体   English

有问题的功能酸洗

[英]Problematic function pickling

In one module, I have a class which requires a function as one of its parameters: 在一个模块中,我有一个类,它需要一个函数作为其参数之一:

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

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

In another module, I have a couple of functions that I eventually pass as parameters when creating this class' objects. 在另一个模块中,我有一些函数,我最终在创建这个类的对象时作为参数传递。 I'm binding values in the following way to easily customize the functions: 我通过以下方式绑定值以轻松自定义函数:

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

When initialising Foo objects, I pass the values like this: 初始化Foo对象时,我传递的值如下:

foo = Foo(sample_function(5))

Later, I want to shelve some objects, including Foo objects, which quickly turned out impossible (as pickle module returns 'TypeError: can't pickle function objects'). 后来,我想搁置一些对象,包括Foo对象,这很快就变得不可能了(因为pickle模块返回'TypeError:不能pickle函数对象')。 I'm fully aware of the limitations of pickle's serialising mechanism, and I realise why pickling these objects is not possible. 我完全了解pickle的序列化机制的局限性,并且我意识到为什么不可能腌制这些对象。 Instead I want to redesign my class, or use other means of serialising. 相反,我想重新设计我的课程,或使用其他序列化方法。 How do I redesign this so that I can shelve Foo objects, while retaining their properties? 我如何重新设计这个以便我可以搁置Foo对象,同时保留它们的属性?

The main problem with your code is the closuse in "sample_function". 您的代码的主要问题是“sample_function”中的closuse。 Without the closure, it can be done with marshal and types modules, here's some example: 没有闭包,可以使用marshal和类型模块来完成,这里有一些例子:

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)

With this classes and function, you can save: 使用此类和函数,您可以保存:

foo = Foo(sample_function)

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

and load: 并加载:

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

The idea is to marshal the "fun" before pickling (and restore it, so the class is not broken) and to load the marshaled code as a function when loading. 这个想法是在酸洗之前编组“有趣”(并恢复它,因此不会破坏类)并在加载时将编组的代码作为函数加载。

But that won't works with closures (because the closure needs variables from the calling function). 但这不适用于闭包(因为闭包需要来自调用函数的变量)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM