我想腌制一个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()
Run Code Online (Sandbox Code Playgroud)
这会产生以下输出:
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
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?问题Bar是成员Foo吗?(将定义Bar移到顶层可以解决问题,尽管我仍然很好奇为什么会发生这种情况.)
Amb*_*ber 30
是的,它是一个类成员的事实是一个问题:
>>> 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'>
Run Code Online (Sandbox Code Playgroud)
问题是当namedtuple()返回一个类型对象时,它不知道它被分配给一个类成员 - 因此,它告诉类型对象它的类型名称应该是__main__.Bar,即使它应该是真的__main__.Foo.Bar.
nos*_*klo 13
嵌套类使得pickle失败,因为它依赖于应用程序内部对象的路径以便以后重构它.
直接的解决方案是不嵌套类,即将Bar定义移到外部Foo.代码将完全相同.
但更好的办法是根本不用 pickle来存储数据.使用一些其他序列化格式,如json,或数据库,如sqlite3.
你刚刚遇到了很多不便之处,如果你改变代码,移动东西,或者有时进行小的结构改变,你的数据就会变得无法加载.
除此之外,泡菜还有其他缺点:它很慢,不安全,只有python ......
| 归档时间: |
|
| 查看次数: |
42867 次 |
| 最近记录: |