如何为dill的pickleable类型添加自定义类型

时间:2014-12-08 05:33:39

标签: python pymongo dill

我正在尝试序列化一些我没有编写的代码,并且无法修改需要进行pickle / dilled的代码。该脚本包含一个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行)我怀疑这是我可以改变某些东西以允许新类型的地方。

但是,我不清楚添加自定义类型的目标界面是什么。 (或者也许是为了除了那些之外的所有东西的酸洗,这是可能还是更容易?)

1 个答案:

答案 0 :(得分:4)

不,dill._objects模块只是一个dill可以且不能腌制的类型列表。除此之外,只会让dill认为它可以做得更多,同时在功能上保持不变。

如果您想添加一个pickler,请使用dill.register(通常用作装饰器)。它需要一个能够分解的功能。例如。鉴于一个不可撼动的课程:

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

您可以定义一个选择器,如:

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元组,在加载时会传递给你的reconstructer函数。

这可能是最灵活的方式,因为您可以使用recreate_A的任何功能,包括A.__init__,如果您需要,但是当您尝试挑选更复杂的类型时,您可能需要进行前/后处理。跳过对象的功能是still in the works,所以如果你想这样做,就必须等待。如果你想达到同样的效果,你可以定义recreate_A来返回None,并且不带args。