【问题标题】:How to add a custom type to dill's pickleable types如何将自定义类型添加到 dill 的 pickleable 类型
【发布时间】:2014-12-08 05:33:39
【问题描述】:

我正在尝试序列化一些我没有编写并且无法修改需要腌制/处理的代码。该脚本包含一个 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 行),我怀疑这是我可能会更改某些内容以允许新类型的地方。

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

【问题讨论】:

    标签: python pymongo dill


    【解决方案1】:

    不,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
    

    你可以像这样定义一个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__,但是当您尝试腌制更复杂的类型时,您可能需要进行预处理/后处理。跳过对象的功能是still in the works,所以如果你想这样做,你必须等待。如果你想达到同样的效果,你可以定义recreate_A返回None,并且不带任何参数。

    【讨论】:

    • 如果你想 fork dill 将你的特定类型添加到 dill... 然后按照 @matsjoyce 所说的做,但是你可以编辑文件 dill.dill.py 直接添加你的类型而不是registering它。如果您查看dill.dill,它基本上是这些registered 函数的集合。我预计dill 不会负责显式管理此类奇异的第 3 方类型——但是,如果您发现导致问题的非常常见的底层类型,那么它更有可能获得成功的 PR。
    • Mike McKerns,如果我想添加新类型但无法在我的环境中直接编辑 dill 源代码,您有什么建议吗?这是猴子补丁的情况吗?
    • 按照我在回答中所说的做?你不需要为此编辑 dill。
    • 明明recreate_A是反序列化器,但是如何指定序列化器呢?
    • save_A 是序列化程序。
    猜你喜欢
    • 2012-07-29
    • 2011-08-10
    • 2010-11-25
    • 2020-05-14
    • 2013-08-04
    • 2017-04-21
    • 1970-01-01
    • 2016-06-15
    • 2017-12-03
    相关资源
    最近更新 更多