Python:无法腌制类型 X,属性查找失败

Posted

技术标签:

【中文标题】Python:无法腌制类型 X,属性查找失败【英文标题】:Python: Can't pickle type X, attribute lookup failed 【发布时间】:2011-06-08 07:12:49 【问题描述】:

我正在尝试腌制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()

这会产生以下输出:

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

我做错了什么?问题是BarFoo 的成员吗? (将Bar 的定义移到顶层可以解决问题,尽管我仍然很好奇为什么会发生这种情况。)

【问题讨论】:

使用 python3 和 pickle 协议 4 解决了这个问题 @DaveButler 的回答是否正确?谁能确认或否认? 【参考方案1】:

是的,它是一个类成员这一事实是个问题:

>>> 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'>

问题是当namedtuple()返回一个类型对象时,它并不知道它被分配给一个类成员的事实——因此,它告诉类型对象它的类型名称应该是__main__.Bar ,即使它确实应该是__main__.Foo.Bar

【讨论】:

namedtuple 只是不适合类。您也许可以为将手动处理它的对象编写自定义 __getstate__ 早期绑定会抓住那个吗? 我如何使用 getstate?我不知道如何实现。目前我正在使用一个临时解决方案,将命名元组列表传输到字典。【参考方案2】:

嵌套类会使 pickle 失败,因为它依赖于应用程序内部对象的路径来稍后重建它。

直接的解决方案是不嵌套类,即将Bar 定义移到Foo 之外。代码将完全一样。

但更好的做法是不使用 pickle 来存储数据。使用其他一些序列化格式,如json,或数据库,如sqlite3

您刚刚遇到了 pickle 的诸多不便之一,如果您更改代码、移动内容或有时进行小的结构更改,您的数据将变得无法加载。

除此之外,pickle 还有其他缺点:速度慢、不安全、仅限 python...

【讨论】:

【参考方案3】:

在这里使用莳萝代替泡菜可以实现这一点

【讨论】:

import dill; dill.dumps(x) 这对我也不起作用。我得到:不能腌制 :它不是 main.RoadAttributesPartition【参考方案4】:

这里的解决方案是将您的命名元组定义移动到模块级别,然后 pickle 工作。这里提供了详细的答案:

How to pickle a namedtuple instance correctly

【讨论】:

以上是关于Python:无法腌制类型 X,属性查找失败的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:无法腌制 dict_items 对象

构建 Python 扩展失败(“kernel32.lib”无法打开 |“x64”与目标机器类型“x86”冲突)

python 属性错误:无法腌制本地对象。使用多处理

在 Kotlin 中无法“findViewById”。收到错误“类型推断失败”

InterfaceError:执行操作失败; Python 类型 numpy.int64 无法转换

Python中的Mongodb聚合:无法腌制'SSLContext'对象