【发布时间】:2020-09-13 22:08:45
【问题描述】:
我正在尝试腌制我在脚本中生成的对象以在之后处理它们,但我收到此错误:
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 函数如下所示:
进口泡菜
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)
解决方案
好吧,在进一步挖掘之后,我发现here,pickle 与 dict 不能很好地混合,并且经常会崩溃。
所以解决方法是我完全放弃了 Attribute 类,现在我的 Person 的 _attribute 是一个 dict 字符串 self._attributes = str(dict()) 并且无论何时我想给它加点东西,我会再做一个 eval()、update() 和 str()。
到目前为止,这似乎有效......
【问题讨论】:
-
附带说明,您可能希望对属性使用单下划线,如
_name和_attributes,而不是双下划线。前者是表示属性是实现细节的约定,而后者是invokes name mangling。 -
我们可以得到minimal reproducible example吗?
-
由于 pickle 抱怨超出递归深度,我认为您的字典没有引起问题。你能提供更多的源代码吗?也许您根据字典的内容实现了一些具有深度的递归函数?
-
@MinhNguyen 我编辑了我的帖子以包含更多信息。我尝试根据内存和类型检查属性字典,无论我使用我的函数还是手动创建它,它们都是相同的
-
你为什么在这里使用
@property?您的任何属性都不会从中受益——它适用于公共属性与实例变量不完全对应的情况(设置某些东西有副作用,读取值涉及计算等)。跨度>