Last active
November 7, 2024 09:12
-
-
Save wmvanvliet/384c0cae564dfcc1cc9095b1401fed0c to your computer and use it in GitHub Desktop.
Example of the non-backwards compatibility of pickle files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pickle | |
class MyClass: | |
"""Example class to pickle. Version 2.""" | |
def __init__(self, a, b, c, d=4): | |
"""New field `d` with default value, so no problems right?""" | |
self.a = a | |
self.b = b | |
self.c = c | |
self.d = d | |
def __repr__(self): | |
return f"{self.a=}, {self.b=}, {self.c=}, {self.d=}" | |
with open("my_data.pkl", "rb") as f: | |
my_data = pickle.load(f) | |
print(my_data) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pickle | |
class MyClass: | |
"""Example class to pickle. Version 3. Now with backwards compatibility!""" | |
def __init__(self, a, b, c, d=4): | |
self.a = a | |
self.b = b | |
self.c = c | |
self.d = d | |
def __repr__(self): | |
return f"{self.a=}, {self.b=}, {self.c=}, {self.d=}" | |
def __setstate__(self, state): | |
"""Called when un-pickling. Make sure fields have default values.""" | |
self.a = state.get("a", 1) | |
self.b = state.get("b", 2) | |
self.c = state.get("c", 3) | |
self.d = state.get("d", 4) | |
with open("my_data.pkl", "rb") as f: | |
my_data = pickle.load(f) | |
print(my_data) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pickle | |
class MyClass: | |
"""Example class to pickle. Version 1.""" | |
def __init__(self, a, b, c): | |
"""No field `d` yet.""" | |
self.a = a | |
self.b = b | |
self.c = c | |
def __repr__(self): | |
return f"{self.a=}, {self.b=}, {self.c=}" | |
my_data = MyClass(1, 2, 3) | |
print(my_data) | |
with open("my_data.pkl", "wb") as f: | |
pickle.dump(my_data, f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
First run
test_pickle_produce.py
, this will produce a pickled filemy_data.pkl
. Then try to runtest_pickle_consume.py
to load in the data. Only now theMyClass
class has been updated with an additional field. Loading the data doesn't work anymore :(The solution is to provide a default value ford
inMyClass.__init__
.The solution is to write custom
MyClass.__getstate__
andMyClass.__setstate__
methods. Seetest_pickle_consume_fixed.py
for an example.