Dec-03-2020, 07:22 AM
I wrote a little test program to understand pickling and unpickling a custom class.
Pickling a custom class by passing it as a parameter to a function that does the pickling works just fine. Trying to unpickle in the same way does not work. You have to make the unpickling function return the unpickled data as the function value and assign the function result to the class instance outside of the function.
Why is that? Any explanation you can provide would be appreciated.
Example code and output for the non-working and working versions are below. System is WIn10-64, Python is 3.8.5.
Peter
Unpickling inside a function does not work:
tstpikl1.py:
tstpikl2.py:
Pickling a custom class by passing it as a parameter to a function that does the pickling works just fine. Trying to unpickle in the same way does not work. You have to make the unpickling function return the unpickled data as the function value and assign the function result to the class instance outside of the function.
Why is that? Any explanation you can provide would be appreciated.
Example code and output for the non-working and working versions are below. System is WIn10-64, Python is 3.8.5.
Peter
Unpickling inside a function does not work:
tstpikl1.py:
import numpy as np class Pkltest: def __init__(self): self.vect = np.full([5, 5], 0, dtype=np.int32) self.int1 = 0 self.real1 = 0.0 self.bool1 = False def saveclass(class2pkl, savename): try: fp = open(savename, "wb") except IOError: print("Can't open file {}".format(savename)) raise from pickle import dump dump(class2pkl, fp) fp.close() return def restclass(class2lod, loadname): try: fp = open(loadname, "rb") except IOError: print("Can't open file {}".format(loadname)) raise from pickle import load class2lod = load(fp) fp.close() return savename = "classsave.pkl" pktest1 = Pkltest() pktest1.vect[1:-1, 1:-1] = 10 pktest1.int1 = 10 pktest1.real1 = 10 pktest1.bool1 = True print("1)Before function save:\n{}\n".format(pktest1.__dict__)) saveclass(pktest1, savename) pktest1.vect[1:-1, 1:-1] = 5 pktest1.int1 = 5 pktest1.real1 = 5 pktest1.bool1 = False print("2)After modify:\n{}\n".format(pktest1.__dict__)) restclass(pktest1, savename) print("3)After function load:\n{}\n".format(pktest1.__dict__)) try: fp = open(savename, "rb") except IOError: print("Can't open file {}".format(savename)) raise from pickle import load pktest1 = load(fp) fp.close() print("4)After inline load:\n{}\n".format(pktest1.__dict__))Output from tstpikl1.py:
Output:1)Before function save:
{'vect': array([[ 0, 0, 0, 0, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 0, 0, 0, 0]]), 'int1': 10, 'real1': 10, 'bool1': True}
2)After modify:
{'vect': array([[0, 0, 0, 0, 0],
[0, 5, 5, 5, 0],
[0, 5, 5, 5, 0],
[0, 5, 5, 5, 0],
[0, 0, 0, 0, 0]]), 'int1': 5, 'real1': 5, 'bool1': False}
3)After function load:
{'vect': array([[0, 0, 0, 0, 0],
[0, 5, 5, 5, 0],
[0, 5, 5, 5, 0],
[0, 5, 5, 5, 0],
[0, 0, 0, 0, 0]]), 'int1': 5, 'real1': 5, 'bool1': False}
4)After inline load:
{'vect': array([[ 0, 0, 0, 0, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 0, 0, 0, 0]]), 'int1': 10, 'real1': 10, 'bool1': True}
Unpickling outside of a function works:tstpikl2.py:
import numpy as np class Pkltest: def __init__(self): self.vect = np.full([5, 5], 0, dtype=np.int32) self.int1 = 0 self.real1 = 0.0 self.bool1 = False def saveclass(class2pkl, savename): try: fp = open(savename, "wb") except IOError: print("Can't open file {}".format(savename)) raise from pickle import dump dump(class2pkl, fp) fp.close() return def restclass(loadname): try: fp = open(loadname, "rb") except IOError: print("Can't open file {}".format(loadname)) raise from pickle import load class2lod = load(fp) fp.close() return class2lod savename = "classsave.pkl" pktest1 = Pkltest() pktest1.vect[1:-1, 1:-1] = 10 pktest1.int1 = 10 pktest1.real1 = 10 pktest1.bool1 = True print("1)Before function save:\n{}\n".format(pktest1.__dict__)) saveclass(pktest1, savename) pktest1.vect[1:-1, 1:-1] = 5 pktest1.int1 = 5 pktest1.real1 = 5 pktest1.bool1 = False print("2)After modify:\n{}\n".format(pktest1.__dict__)) pktest1 = restclass(savename) print("3)After function load:\n{}\n".format(pktest1.__dict__))Output from tstpikl2.py:
Output:1)Before function save:
{'vect': array([[ 0, 0, 0, 0, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 0, 0, 0, 0]]), 'int1': 10, 'real1': 10, 'bool1': True}
2)After modify:
{'vect': array([[0, 0, 0, 0, 0],
[0, 5, 5, 5, 0],
[0, 5, 5, 5, 0],
[0, 5, 5, 5, 0],
[0, 0, 0, 0, 0]]), 'int1': 5, 'real1': 5, 'bool1': False}
3)After function load:
{'vect': array([[ 0, 0, 0, 0, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 10, 10, 10, 0],
[ 0, 0, 0, 0, 0]]), 'int1': 10, 'real1': 10, 'bool1': True}