Nov-23-2024, 02:15 PM
[deadeye@nexus ~]$ ipython Python 3.13.0 (main, Oct 8 2024, 16:30:59) [GCC 14.2.1 20240910] Type 'copyright', 'credits' or 'license' for more information IPython 8.29.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: import pickle ...: ...: ...: class Foo: ...: def __init__(self, name): ...: self.name = name ...: ...: def hello(self): ...: print(f"Hello {self.name}") ...: ...: ...: with open("test_pickle.pickle", "wb") as fd: ...: # pickle the resulting instance of Foo ...: # and write it to the open file in binary mode ...: pickle.dump(Foo("Maya"), fd) ...: ...: ...: # now the pitfall ...: # you decided to change you class, but you still have old instances ...: class Foo: ...: def __init__(self, name): ...: self.identity = name ...: ...: def hello(self): ...: print(f"Hello {self.identity}") ...: ...: ...: # now Foo is a different class, whith a different attribute and method ...: # trying to load the instance ...: with open("test_pickle.pickle", "rb") as fd: ...: foo_instance = pickle.load(fd) ...: ...: foo_instance.hello() ---------------------------------------------------------------------------
Error:AttributeError Traceback (most recent call last)
Cell In[1], line 33
30 with open("test_pickle.pickle", "rb") as fd:
31 foo_instance = pickle.load(fd)
---> 33 foo_instance.hello()
Cell In[1], line 25, in Foo.hello(self)
24 def hello(self):
---> 25 print(f"Hello {self.identity}")
AttributeError: 'Foo' object has no attribute 'identity'
Btw. ipython is a better REPL. But often I use ptpython, which has a better way to show the signature of functions/methods incl. the docstrings.Another solution could be to write the data of your class into a serializable format (json) and if you want to restore the instance, loading from the file and creatng a new instance of the slightly modified class.
import json class Foo: def __init__(self, name): self.name = name def hello(self): print(f"Hello {self.name}") def save(self, file): with open(file, "w") as fd: json.dump({"name": self.name}, fd) @classmethod def load(cls, file): with open(file) as fd: data = json.load(fd) return cls(name=data.get("name", "DEFAULT")) class FooNew: def __init__(self, identity): self.identity = identity def hello(self): print(f"Hello {self.identity}") def save(self, file): with open(file, "w") as fd: json.dump({"identity": self.identity}, fd) @classmethod def load(cls, file): """ Load FooNew instances and beeing compatible to old Foo instances. """ with open(file) as fd: data = json.load(fd) identity = data.get("identity") or data.get("name") or "DEFAULT" return cls(identity) old_foo = Foo("Nick") old_foo.save("old_foo.json") new_foo = FooNew.load("old_foo.json") print("Hello from old_foo") old_foo.hello() print("Hello from new_foo") new_foo.hello() print("Vars of old_foo", vars(old_foo)) print("Vars of new_foo", vars(new_foo))
Output:Hello from old_foo
Hello Nick
Hello from new_foo
Hello Nick
Vars of old_foo {'name': 'Nick'}
Vars of new_foo {'identity': 'Nick'}
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
All humans together. We don't need politicians!