【问题标题】:pickling and unpickling user-defined class酸洗和解酸用户定义的类
【发布时间】:2015-03-20 16:23:15
【问题描述】:

我有一个用户定义的类“myclass”,我使用pickle 模块存储在文件中,但是我在解开它时遇到了问题。我有大约 20 个相同结构的不同实例,我将它们保存在不同的文件中。当我阅读每个文件时,当我收到错误时,代码适用于某些文件而不适用于其他文件:

'module' object has no attribute 'myclass'

我今天生成了一些文件,昨天生成了一些文件,我的代码仅适用于今天生成的文件(我没有更改昨天和今天之间的类定义)。

我想知道我的方法是否不可靠,如果我没有按照我应该做的事情去做,例如我可能无法腌制用户定义的类,以及这是否会在过程中引入一些随机性。

另一个问题可能是我昨天生成的文件是在另一台机器上生成的——因为我在一个学术集群上工作,我有一些登录节点和一些计算节点,它们因架构而异。所以我在计算节点上生成了昨天的文件,在登录节点上生成了今天的文件,我正在读取登录节点上的所有内容。


按照某些 cmets 的建议,我已安装 dill 并使用 import dill as pickle 加载它。现在我可以从计算节点读取文件到同一个集群的登录节点。但是如果我尝试读取在一个集群的计算节点上生成的文件,在另一个集群的登录节点上我不能。我在 dill.py 的 _load_type(name) 中得到 KeyError: 'ClassType'

会不会是因为python版本不一样?我用python2.7生成了文件,用python3.3读取它们。


编辑:

如果我在任何地方都使用 python 2.7,我可以读取腌制文件。可悲的是,我用 python 3 编写的部分代码不能自动与 python 2.7 兼容:(

【问题讨论】:

  • 听起来好像使用的 python 版本/库可能不同。
  • 看看docs.python.org/3/library/pickle.html#data-stream-format - 您可能需要明确设置协议。
  • 如果 python 的版本或任何库的版本不同,您的腌制对象可能无法在机器之间转换(借调@MarcusMüller)。当您看到'module' object has no attribute 'myclass' 时,这意味着正在加载module,但在其中找不到对myclass 的引用。当包在内部移动一个函数或一个类并留下一个名称引用或(更糟糕的)一个类的实例以保持向后兼容性时,通常会发生这种情况。您看到的错误对于 curried 函数和对类实例的引用也很常见。
  • 您可以使用序列化程序(如dill),它可以选择腌制整个类定义(而不是通过引用),这可能会使您与不同版本的python或库/图书馆。然而,它不会对已经构建的泡菜做任何事情。
  • 设置协议并不能解决我的问题,但现在我使用dill,它可以工作

标签: python pickle


【解决方案1】:

你能from mymodule import myclass吗? Pickling 不会腌制类,只是对它的引用。要加载腌制对象,python 必须能够找到用于创建对象的类。

例如。

import pickle

class A(object):
    pass

obj = A()
pickled = pickle.dumps(obj)

_A = A; del A # hide class

try:
    pickle.loads(pickled)
except AttributeError as e:
    print(e)

A = _A # unhide class
print(pickle.loads(pickled))

【讨论】:

猜你喜欢
  • 2014-08-13
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多