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}
