如何通过 cloudpickle 腌制 python-attrs class 函数?
How to pickle python-attrs class functions via cloudpickle?
我正在使用 cloudpickle 传递函数,我想通过 cloudpickle 传递一个 attrs
class 函数。
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())
运行 这给了我 1 + test + 2.4
虽然 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())
给我错误:TypeError: can't pickle _thread._local objects
(我会 post 底部的完整错误日志)
我确信我需要实现一些 __getstate__
或 __reduce__
函数来让 cloudpickle 腌制 class,但我都尝试过但没有任何运气。
添加功能:
def __reduce__(self):
return (self.__class__, (self.an_int, self.a_str, self.a_float))
给出同样的错误
我应该实施什么才能实现这一目标?
python 错误日志:
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
这是由于 attrs
在 __repr__
中使用线程局部变量来分解对象循环,而 cloudpickle 不喜欢这样。作为参考,它是在https://github.com/python-attrs/attrs/pull/358.
中介绍的
您的快速解决方法是设置 @attr.s(repr=False)
,但请随时在我们的错误跟踪器上提出问题,我们可以讨论如何进行。
我正在使用 cloudpickle 传递函数,我想通过 cloudpickle 传递一个 attrs
class 函数。
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())
运行 这给了我 1 + test + 2.4
虽然 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())
给我错误:TypeError: can't pickle _thread._local objects
(我会 post 底部的完整错误日志)
我确信我需要实现一些 __getstate__
或 __reduce__
函数来让 cloudpickle 腌制 class,但我都尝试过但没有任何运气。
添加功能:
def __reduce__(self):
return (self.__class__, (self.an_int, self.a_str, self.a_float))
给出同样的错误
我应该实施什么才能实现这一目标?
python 错误日志:
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
这是由于 attrs
在 __repr__
中使用线程局部变量来分解对象循环,而 cloudpickle 不喜欢这样。作为参考,它是在https://github.com/python-attrs/attrs/pull/358.
您的快速解决方法是设置 @attr.s(repr=False)
,但请随时在我们的错误跟踪器上提出问题,我们可以讨论如何进行。