Python:无法pickle类型X,属性查找失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4677012/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python: Can't pickle type X, attribute lookup failed
提问by Nick Heiner
I am trying to pickle a namedtuple:
我正在尝试腌制一个namedtuple:
from collections import namedtuple
import cPickle
class Foo:
Bar = namedtuple('Bar', ['x', 'y'])
def baz(self):
s = set()
s.add(Foo.Bar(x=2, y=3))
print cPickle.dumps(s)
if __name__ == '__main__':
f = Foo()
f.baz()
This produces the following output:
这会产生以下输出:
Traceback (most recent call last):
File "scratch.py", line 15, in <module>
f.baz()
File "scratch.py", line 11, in baz
print cPickle.dumps(s)
cPickle.PicklingError: Can't pickle <class '__main__.Bar'>: attribute lookup __main__.Bar failed
What am I doing wrong? Is the problem that Baris a member of Foo? (Moving the definition of Barto the top level solves the problem, although I'm still curious why this happens.)
我究竟做错了什么?是Bar成员的问题Foo吗?(将 的定义Bar移到顶层解决了问题,尽管我仍然很好奇为什么会发生这种情况。)
采纳答案by Amber
Yes, the fact that it's a class member is a problem:
是的,它是班级成员这一事实是一个问题:
>>> class Foo():
... Bar = namedtuple('Bar', ['x','y'])
... def baz(self):
... b = Foo.Bar(x=2, y=3)
... print(type(b))
...
>>> a = Foo()
>>> a.baz()
<class '__main__.Bar'>
The problem is that when namedtuple()returns a type object, it isn't aware of the fact that it's being assigned to a class member - and thus, it tells the type object that its type name should be __main__.Bar, even though it should really be __main__.Foo.Bar.
问题是当namedtuple()返回一个类型对象时,它不知道它被分配给一个类成员的事实 - 因此,它告诉类型对象它的类型名称应该是__main__.Bar,即使它真的应该是__main__.Foo.Bar。
回答by nosklo
Nesting classes makes pickle fail, since it relies on the path of the object inside your application to reconstruct it later.
嵌套类会使 pickle 失败,因为它依赖于应用程序内部对象的路径来稍后重建它。
The immediate solution is to not nest classes, i.e. move Bardefinition to outside Foo. Code will work all the same.
直接的解决方案是不嵌套类,即将Bar定义移动到外部Foo。代码将完全相同。
But a better thing to do is to not usepickleat all to store data. Use some other serialization format, like json, or a database, like sqlite3.
但更好的做法是根本不使用pickle来存储数据。使用其他一些序列化格式,如json,或数据库,如sqlite3.
You have just hit one of the many inconveniences of pickle, if you change your code, move things around, or sometimes make small structural changes, your data becomes unloadable.
您刚刚遇到了pickle 的众多不便之一,如果您更改代码、移动内容或有时进行小的结构更改,您的数据将无法加载。
Besides that, pickle has other disadvantages: It is slow, unsecure, python-only...
除此之外,pickle 还有其他缺点:它很慢、不安全、只支持 Python...
回答by Maximilian
Using dill in place of pickle here will allow this to work
在这里使用莳萝代替泡菜将允许它工作
回答by David Parks
The solution here is to move your named tuple definition to the module level, then pickle works. A detailed answer is provided here:
这里的解决方案是将您的命名元组定义移动到模块级别,然后 pickle 工作。这里提供了详细的答案:

