在python3.7下,当"recurse“设置设置为True时,dill无法选择sympy.Float对象:
dill.settings["recurse"] = True
import sympy
tst = sympy.Float(3.3)
dill.detect.errors(tst)这在RecursionError('maximum recursion depth exceeded in comparison')中失败了。有人知道解决办法吗?
对于Python,错误会消失,在没有“>=3.8”设置的情况下也不会发生错误。不幸的是,我需要支持Python3.7,并且被迫使用"recurse“模式。
发布于 2022-08-12 13:01:34
将泡菜协议从3更改为4:
import dill
dill.settings["recurse"] = True
dill.settings["protocol"] = 4 # Add this
import sympy
tst = sympy.Float(3.3)
dill.detect.errors(tst)在Python3.8及更高版本中,pickle设置DEFAULT_PROTOCOL = 4。
解释
pickle save_reduce,如果协议< 4,则保存func而不是Float类:if self.proto >= 4:
save(cls)
save(args)
save(kwargs)
write(NEWOBJ_EX)
else:
func = partial(cls.__new__, cls, *args, **kwargs)
save(func)
save(())
write(REDUCE)带有"recurse“= True的
dill递归地跟踪和挑选全局函数字典中引用的对象(从cls.__new__开始,即cls.__new__)sympy在Float.__new__→_convert_numpy_types→sympify→_convert_numpy_types (重复)→.中有循环引用。
概念证明
您可以使用以下方法再现错误:
def a():
b
def b():
a
import dill
dill.settings["recurse"] = True
dill.detect.errors(a)发布于 2022-08-11 21:03:57
我是dill的作者。我没看到报道的行为。也许您使用的是较早版本的Python、dill或sympy。
Python 3.7.13 (default, May 10 2022, 11:13:40)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> import sympy
>>> dill.__version__
'0.3.6.dev0'
>>> sympy.__version__
'1.10.1'
>>> tst = sympy.Float(3.3)
>>> dill.copy(tst)
3.30000000000000
>>> dill.settings['recurse'] = True
>>> dill.copy(tst)
3.30000000000000
>>> dill.detect.errors(tst)
>>> 在这里,copy(tst)和loads(dumps(tst))是一样的。如果您的版本比我的版本早,并且在更新之后,您仍然会看到相同的行为(或者它对您来说仍然存在),那么请在注释中让我知道(并在dill GitHub页面上填写一个问题)。
注意:我们有一个即将发布的版本,所以dill-0.3.6将在几天内发布。
https://stackoverflow.com/questions/73321138
复制相似问题