1

我正在尝试序列化一些我没有编写并且无法修改需要腌制/挖掘的代码。该脚本包含一个 mongodb 集合对象——它实际上并没有在以后使用,但是对其进行挖掘会引发错误。当我尝试挖掘它时,我收到错误:

Collection object is not callable.  If you meant to call __getnewargs__ method on a 'Database' object it is failing because no such method exists.

我在这里看到枚举接受类型的代码: https://github.com/uqfoundation/dill/blob/master/dill/_objects.py(第 132-190 行),我怀疑这是我可能会改变的地方允许新类型。

但是,我不清楚添加自定义类型的预期接口是什么。(或者也许为了腌制除此之外的所有东西,这可能还是更容易?)

4

1 回答 1

4

不,该dill._objects模块只是莳萝可以泡菜和不能泡菜的类型列表。再加上它只会让人dill觉得它可以做更多事情,同时在功能上保持不变。

如果要添加pickler,请使用dill.register(通常用作装饰器)。它需要一个功能来分解。例如,给定一个 unpicklable 类:

class A:
    def __init__(self, a):
        self.a = a
    def __reduce__(self):
        raise GoAwayError()

试图腌制一个实例A会给你:

Traceback (most recent call last):
  File "d.py", line 9, in <module>
    dill.dumps(A(1))
  File "/home/matthew/GitHub/dill/dill/dill.py", line 192, in dumps
    dump(obj, file, protocol, byref, fmode)#, strictio)
  File "/home/matthew/GitHub/dill/dill/dill.py", line 182, in dump
    pik.dump(obj)
  File "/usr/lib/python3.4/pickle.py", line 410, in dump
    self.save(obj)
  File "/usr/lib/python3.4/pickle.py", line 497, in save
    rv = reduce(self.proto)
  File "d.py", line 7, in __reduce__
    raise GoAwayError()
NameError: name 'GoAwayError' is not defined

您可以定义一个pickler,如:

def recreate_A(a):
    return A(a)

@dill.register(A)
def save_A(pickler, obj):
    pickler.save_reduce(recreate_A, (obj.a,), obj=obj)

recreate_A是用于重建的函数,(obj.a,)是一个 args 元组,加载时将传递给你的重建函数。

这可能是最灵活的方法,因为您可以使用任何函数recreate_A,包括A.__init__如果需要,但是当您尝试腌制更复杂的类型时,您可能需要进行预处理/后处理。跳过对象的功能仍在开发中,因此如果您想这样做,则必须等待。如果你想达到同样的效果,你可以定义recreate_A为返回 None,并且不带任何参数。

于 2014-12-08T09:12:12.690 回答