【问题标题】:Why can't instances of this subclass of set be unpickled?为什么不能解开这个 set 子类的实例?
【发布时间】:2019-10-10 16:15:05
【问题描述】:

当我将类实例转储到带有 pickle 模块的文件时,它是成功的,但是,当我从文件中加载实例时,它失败并引发 TypeError 异常。

我发现从 set 派生的所有子类在尝试解开它时都会引发 TypeError

class TreeKeys(set):
    def __init__(self):
        super(TreeKeys, self).__init__()

    def add(self, tk):
        assert tk.__class__ == tuple
        super(TreeKeys, self).add(tk)


if __name__ == '__main__':
    a = TreeKeys()
    a.add((1,2,3))
    with open('tmp.pickle', 'wb') as tmp_fd:
        pickle.dump(a, tmp_fd)
    with open('tmp.pickle', 'rb') as tmp_fd:
        obj = pickle.load(tmp_fd)  # this is the code line raise the TypeError exception.
    pass
Connected to pydev debugger (build 182.3684.100)
Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.2\helpers\pydev\pydevd.py", line 1664, in <module>
    main()
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.2\helpers\pydev\pydevd.py", line 1658, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2018.2\helpers\pydev\pydevd.py", line 1068, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "G:/pycharm-projects/new_keyinfo/verify_treekeys.py", line 56, in <module>
    obj = pickle.load(tmp_fd)
  File "C:\Python27_64bit\Lib\pickle.py", line 1384, in load
    return Unpickler(file).load()
  File "C:\Python27_64bit\Lib\pickle.py", line 864, in load
    dispatch[key](self)
  File "C:\Python27_64bit\Lib\pickle.py", line 1139, in load_reduce
    value = func(*args)
TypeError: __init__() takes exactly 1 argument (2 given)

Process finished with exit code -1

【问题讨论】:

    标签: python python-2.7 set pickle


    【解决方案1】:

    问题是你没有定义你的类的 __init__() 方法来接受一个(可选的)可迭代参数,就像它的基类一样,内置的 set 类做了,pickle 试图用它来调用它用于在加载文件时恢复实例的内容。

    这里有一个简单的方法来解决这个问题:

    import pickle
    
    class TreeKeys(set):
        def __init__(self, iterable=None):
            if iterable is None:
                super(TreeKeys, self).__init__()
            else:
                super(TreeKeys, self).__init__(iterable)
    
        def add(self, tk):
            assert tk.__class__ == tuple
            super(TreeKeys, self).add(tk)
    
    
    if __name__ == '__main__':
        a = TreeKeys()
        a.add((1,2,3))
        with open('tmp.pickle', 'wb') as tmp_fd:
            pickle.dump(a, tmp_fd)
        with open('tmp.pickle', 'rb') as tmp_fd:
            obj = pickle.load(tmp_fd)  # This will now work.
        print(obj)  # -> TreeKeys([(1, 2, 3)])
    

    【讨论】:

    • 它现在真的可以工作了,但是,使用我提供的原始代码,我将集合替换为列表,它可以工作。 list 和 set 的 __init() 方法都有一个可选的可迭代参数,为什么 list 的子类可以工作,而 set 的子类却不行?你知道这个问题的根本原因,或者,你能详细说明这个问题的根本原因吗?谢谢。
    • 这可能和this problem有同样的问题
    猜你喜欢
    • 1970-01-01
    • 2012-12-23
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 2023-04-06
    • 2010-11-14
    • 1970-01-01
    相关资源
    最近更新 更多