I have custom list and dictionary classes that no longer work while unpickling in Python 3.7.
import pickle
class A(dict):
pass
class MyList(list):
def __init__(self, iterable=None, option=A):
self.option=option
if iterable:
for x in iterable:
self.append(x)
def append(self, obj):
if isinstance(obj, dict):
obj = self.option(obj)
super(MyList, self).append(obj)
def extend(self, iterable):
for item in iterable:
self.append(item)
if __name__ == '__main__':
pickle_file = 'test_pickle'
my_list = MyList([{'a': 1}])
pickle.dump(my_list, open(pickle_file, 'wb'))
loaded = pickle.load(open(pickle_file, 'rb'))
print(isinstance(loaded[0], A))
Works fine on Python 2.6 through 3.6:
"C:\Program Files\Python36\python.exe" issue.py
True
But is no longer setting the self.option properly in 3.7.
"C:\Program Files\Python37\python.exe" issue.py
Traceback (most recent call last):
File "issue.py", line 28, in <module>
loaded = pickle.load(open(pickle_file, 'rb'))
File "issue.py", line 21, in extend
self.append(item)
File "issue.py", line 16, in append
obj = self.option(obj)
AttributeError: 'MyList' object has no attribute 'option'
If I were to remove the extend function, it works as expected though.
I have tried adding __setstate__ as well, but it is not called before extend so the option is still undefined at that point.
I do have to inherit directly from dict and list, and I do need to overwrite both the append and extend function in my code. Is there a way to set option beforehand or another fix? Is this change in behavior documented and the rational for it?
Thank you for your time