无法腌制对象:超出最大递归深度

问题描述 投票:0回答:2

我正在尝试腌制在脚本中生成的对象以便随后处理它们,但我收到此错误:

File "<ipython-input-2-0f716e86ecd3>", line 1, in <module>
pickle.dump(thisperson, output, pickle.HIGHEST_PROTOCOL)
RecursionError: maximum recursion depth exceeded while pickling an object

这里

thisperson
相对简单(或者我是这么认为的):一个名字和一个包含属性的字典:

class Attributes:
    def __init__(self, what_attr, attr):
        self._what_attr = what_attr
        self._attributes = attr

    @property
    def what_attr(self):
        return self._what_attr
    @what_attr.setter
    def what_attr(self, new_value):
        self._what_attr = new_value

    @property
    def attributes(self):
        return self._attributes
    @attributes.setter
    def attributes(self, new_value):
        self._attributes = new_value


class Person:
    def __init__(self, watname, watage):
        self._myname = watname
        self._age = watage
        self._attributes = []

    @property
    def attributes(self):
        return self._attributes
    @attributes.setter
    def attributes(self, attributes_list):
        self._attributes = attributes_list

    @property
    def myname(self):
        return self._myname
    @myname.setter
    def myname(self, value):
        self._myname = value

    @property
    def age(self):
        return self._age
    @age.setter
    def age(self, value):
        self._age = value

pickle 函数如下所示:

import pickle

def save_person(person, mypath):
    import os
    if not os.path.exists(mypath):
        os.makedirs(mypath)
    my_path = mypath + str(person.myname)
    if not os.path.exists(my_path + '/'):
        os.makedirs(my_path + '/')
    with open(my_path + '.pkl', 'wb') as output:
        pickle.dump(person, output, pickle.HIGHEST_PROTOCOL)

这个错误似乎是由于该类包含一个字符串和一个

dict
的事实,因为如果我将属性保留为空
dict
我不会收到错误。

还有其他方法可以腌制这些物体吗?

我尝试增加

sys.setrecursionlimit
,但这没有帮助。

编辑: ....如果我使用简短版本的代码,我无法重现该错误....想想看。 @MinhNguyen 奇怪的是,我在函数中创建属性字典(attr = get_attributes(data)),但是当我自己创建相同的字典时,我可以腌制它....

thisperson = Person("Kenny", 22, {})
attr = get_attributes(data)  # returns {'eyes': 'blue', 'hair': 'brown'}
this_attr = Attributes(person_name, attr)
this_person.attributes.append(this_attr)
save_person(this_person, main_folder)

Exception ignored in: 
'_pydevd_frame_eval.pydevd_frame_evaluator_win32_37_64.get_bytecode_while_frame_eval'
 RecursionError: maximum recursion depth exceeded while calling a Python object
 Process finished with exit code -1073741819 (0xC0000005)

但是如果我执行以下操作,它就会起作用:

attr = {'eyes': 'blue', 'hair': 'brown'}
this_attr = Attributes(person_name, attr)
this_person.attributes.append(this_attr)
save_person(this_person, main_folder)

解决方案

好吧,经过进一步挖掘,我发现herepickle 与 dict 不能很好地混合,并且经常会崩溃。

所以解决方法是我完全删除了 Attribute 类,现在我的 Person 的 _attribute 是一串 dict self._attributes = str(dict()) 每当我想向其中添加内容时,我都会这样做再次 eval()、update() 和 str()。

到目前为止这似乎有效......

python pickle
2个回答
3
投票

问题

我一直在使用

concurrent.futures
模块,特别是
ProcessPoolExecutor
类,它使用(在幕后)
pickle
模块将值返回到主进程。 这个问题是,当我们谈论嵌套的东西时,
pickle
模块似乎对你可以“pickle-ize”的东西有限制。就我而言,我的结构如下:

data = [
    {
        "string_list": [
            ["a1", "a2", ..., "an"],
            ["b1", "b2", ..., "bn"],
            ...
            ["n1", "n2", ..., "nn"],
        ]
    },
    {
        "string_list": [
            ["a1", "a2", ..., "an"],
            ["b1", "b2", ..., "bn"],
            ...
            ["n1", "n2", ..., "nn"],
        ]
    },

基本上,它是一个字典列表,每个字典都包含一个字符串列表的列表。我的意思是,这是一个相对嵌套的结构。每次我尝试从

data
结果中获取
ProcessPoolExecutor's
时,它都会引发
RecursionError: maximum recursion depth exceeded while pickling an object
,这是由于 pickle 模块(显然)无法处理这种级别的嵌套。

解决方案

我的解决方案与编辑的问题中提供的类似。我在酸洗之前“串化”了结构,然后在可以访问

data
后撤消它。就我个人而言,我使用了 json 模块,该模块还附带了 Python 标准库。

这是我处理pickle模块的“经验”。


1
投票

快速评论:我发现对于我的对象,IntEnum 导致了这个。有一个它的实例,用一堆常量替换它,异常就消失了。

© www.soinside.com 2019 - 2024. All rights reserved.