Message338803
If a dataclass is `frozen` and has `__slots__`, then unpickling an instance of it fails because the default behavior is to use `setattr` which `frozen` does not allow.
```
import pickle
from dataclasses import dataclass
@dataclass(frozen=True)
class A:
__slots__ = ('a',)
a: int
b = pickle.dumps(A(5))
pickle.loads(b)
```
```
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'a'
```
This has a straightforward workaround, namely to use `object.setattr`.
```
import pickle
from dataclasses import dataclass
@dataclass(frozen=True)
class A:
__slots__ = ('a',)
a: int
def __getstate__(self):
return dict(
(slot, getattr(self, slot))
for slot in self.__slots__
if hasattr(self, slot)
)
def __setstate__(self, state):
for slot, value in state.items():
object.__setattr__(self, slot, value)
b = pickle.dumps(A(5))
pickle.loads(b)
```
It would be nice if this was fixed for all frozen, slotted dataclasses.
Originally report on SO: https://stackoverflow.com/questions/55307017/pickle-a-frozen-dataclass-that-has-slots |
|
Date |
User |
Action |
Args |
2019-03-25 15:18:08 | drhagen | set | recipients:
+ drhagen |
2019-03-25 15:18:08 | drhagen | set | messageid: <1553527088.82.0.636469633332.issue36424@roundup.psfhosted.org> |
2019-03-25 15:18:08 | drhagen | link | issue36424 messages |
2019-03-25 15:18:08 | drhagen | create | |
|