【问题标题】:Is there a way to pickle objects so that in separate run to retrieve them有没有办法腌制对象,以便在单独运行中检索它们
【发布时间】:2021-03-11 12:35:44
【问题描述】:

我想知道是否有可能在不提供 MyClass 代码的情况下以某种方式正确读取 pickle 文件。

import pickle


class MyClass:
    def __init__(self, n):
        self._n = n

    def give_vec(self):
        return [1 for _ in range(self._n)]


if __name__ == '__main__':
    m = MyClass(30)

    with open('test.pickle', 'wb') as p:
        pickle.dump(m, p)

假设我们已经运行了上面的代码,现在启动一个 python 解释器并尝试以下操作

>>> import pickle
>>> p = open('test.pickle', 'rb')
>>> a = pickle.load(p)

这样我们就不会得到这个错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Can't get attribute 'MyClass' on <module '__main__' (built-in)>

这个想法是提供一个有一些接口而不指定确切类的泡菜

【问题讨论】:

    标签: python python-3.x serialization pickle


    【解决方案1】:

    很遗憾,只用泡菜是不可能的。

    来自https://docs.python.org/3/library/pickle.html#pickle-picklable

    函数的代码和它的任何函数属性都没有被腌制。因此定义模块必须在 unpickling 环境中是可导入的,并且模块必须包含命名对象,否则会引发异常。

    所以只能腌制数据,而不是关联类的行为。

    但是你可以使用dill

    dill 可用于将 python 对象存储到文件中,但主要用途是将 python 对象作为字节流通过网络发送。 dill 非常灵活,允许对任意用户定义的类和函数进行序列化。

    只需将import pickle 替换为import dill as pickle 即可:

    import dill as pickle
    
    
    class MyClass:
        def __init__(self, n):
            self._n = n
    
        def give_vec(self):
            return [1 for _ in range(self._n)]
    
    
    if __name__ == '__main__':
        m = MyClass(30)
    
        with open('test.pickle', 'wb') as p:
            pickle.dump(m, p)
    
    >>> import dill as pickle
    >>> p = open('test.pickle', 'rb')
    >>> a = pickle.load(p)
    >>> a
    <__main__.MyClass object at 0x7eff33758340>
    

    【讨论】:

    • 我添加了第三方库dill的解决方案。
    • 非常感谢!我刚刚注意到,在我定义 MyClass 的代码中,当我用 cloudpickle 替换 pickle 时它可以工作。
    • 有趣,感谢您的信息!我以前不知道cloudpickle。很高兴看到有多种形式可供选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-20
    • 1970-01-01
    • 2022-01-28
    • 1970-01-01
    • 2010-09-20
    • 2019-06-24
    • 2016-07-12
    相关资源
    最近更新 更多