[英]How to pickle python-attrs class functions via cloudpickle?
I'm using cloudpickle to pass functions around, and I'd like to pass an attrs
class function via cloudpickle.我正在使用 cloudpickle 来传递函数,我想通过 cloudpickle 传递一个
attrs
类函数。
import pickle
import attr
@attr.s(auto_attribs=True)
class myclass:
an_int: int
a_str: str
a_float: float
def myfunc(self):
return f"{self.an_int} + {self.a_str} + {self.a_float}"
mc = myclass(1, "test", 2.4)
f = pickle.loads(pickle.dumps(mc.myfunc))
print(f())
running this gives me 1 + test + 2.4
运行这给了我
1 + test + 2.4
While the cloudpickle implementation而 cloudpickle 的实现
import attr
import cloudpickle
@attr.s(auto_attribs=True)
class myclass:
an_int: int
a_str: str
a_float: float
def myfunc(self):
return f"{self.an_int} + {self.a_str} + {self.a_float}"
mc = myclass(1, "test", 2.4)
f = cloudpickle.loads(cloudpickle.dumps(mc.myfunc))
print(f())
gives me the error: TypeError: can't pickle _thread._local objects
(I'll post the full error log at the bottom)给了我错误:
TypeError: can't pickle _thread._local objects
(我将在底部发布完整的错误日志)
I am confident that I need to implement some __getstate__
or __reduce__
function to get cloudpickle to pickle the class, but I've tried both without any luck.我相信我需要实现一些
__getstate__
或__reduce__
函数来让 cloudpickle 对类进行腌制,但我已经尝试过两者都没有任何运气。
adding the function:添加功能:
def __reduce__(self):
return (self.__class__, (self.an_int, self.a_str, self.a_float))
gives the same error给出同样的错误
What should I be implementing in order to accomplish this?为了实现这一目标,我应该实施什么?
python error log:蟒蛇错误日志:
Traceback (most recent call last):
File "x.py", line 16, in <module>
f = cloudpickle.loads(cloudpickle.dumps(mc.myfunc))
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/site-packages/cloudpickle/cloudpickle.py", line 917, in dumps
cp.dump(obj)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/site-packages/cloudpickle/cloudpickle.py", line 268, in dump
return Pickler.dump(self, obj)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 437, in dump
self.save(obj)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/site-packages/cloudpickle/cloudpickle.py", line 689, in save_instancemethod
self.save_reduce(types.MethodType, (obj.__func__, obj.__self__), obj=obj)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 638, in save_reduce
save(args)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 771, in save_tuple
save(element)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 549, in save
self.save_reduce(obj=obj, *rv)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 633, in save_reduce
save(cls)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/site-packages/cloudpickle/cloudpickle.py", line 664, in save_global
return self.save_dynamic_class(obj)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/site-packages/cloudpickle/cloudpickle.py", line 511, in save_dynamic_class
save(clsdict)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 882, in _batch_setitems
save(v)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/site-packages/cloudpickle/cloudpickle.py", line 408, in save_function
self.save_function_tuple(obj)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/site-packages/cloudpickle/cloudpickle.py", line 573, in save_function_tuple
save(state)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 882, in _batch_setitems
save(v)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 882, in _batch_setitems
save(v)
File "/home/me/.local/share/pyenv/versions/3.7.0/lib/python3.7/pickle.py", line 524, in save
rv = reduce(self.proto)
TypeError: can't pickle _thread._local objects
This is caused by attrs
using thread locals for breaking up object cycles in __repr__
and cloudpickle not liking that.这是由于
attrs
使用线程__repr__
来分解__repr__
对象循环,而 cloudpickle 不喜欢这样。 For reference, it was introduced in https://github.com/python-attrs/attrs/pull/358 .作为参考,它是在https://github.com/python-attrs/attrs/pull/358中介绍的。
Your quick fix is to set @attr.s(repr=False)
but feel free to open an issue on our bug tracker and we can discuss how to proceed.您的快速解决方法是设置
@attr.s(repr=False)
但随时在我们的错误跟踪器上打开一个问题,我们可以讨论如何继续。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.