Python Forum
what is solution to save and reload a object?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
what is solution to save and reload a object?
#1
Dilemma:
In my program, one of my function needs to use a object from past session. However, when session ends, the object is cleared along with the program.
Instead of rerunning the object construction each time my program starts, and save from need to include object's construction script alongside my program.

my thinking is to save this object as binary file or other form to reload later in my program.
I found that pickle could serialize and save pythonic objects as binary file. However, there is a catch:
1. provides imported modules that object uses.
2. provides the definition of the object beforehand.

for me, pickle seems like including the construction script alongside my program in another form.

My question:
1. is there a better solution to my dilemma?
2. if there is not better solution, is there a another way to achieve the saving and reload of this object, so a simple reload would allow my function to function?
Reply
#2
(Nov-22-2024, 03:06 AM)eue Wrote: is there a better solution to my dilemma?
For me, a simple serialization solution is the marshmallow module. You'll need to write some code but I think it's worth it:
  • Write code to convert your object to a dictionary containing simple python types such as lists and dictionaries
  • Write a marshmallow shema class that will handle serialization and deserialization of this dictionary
  • Write code to convert back the dictionary to the target class.
eue likes this post
« We can solve any problem by introducing an extra level of indirection »
Reply
#3
Can you show a minimal code example please? It's not really clear what kind of object this is. It sounds strange to save behaviour as well as state . Why wouldn't you just create the object when your program starts?
buran likes this post
Reply
#4
(Nov-22-2024, 03:06 AM)eue Wrote: for me, pickle seems like including the construction script alongside my program in another form
This is true but it is not difficult to implement. Below is an example of a class that will save it’s own current state. Save this in a file called “self_saving.py”. You can add to it whatever methods you want to create the object that you need.
#
# Class to create instance that will save and load it's own state
#
import pickle

class Self_Saving_Class () :
	def __init__ (self, instance_name) :
		self.file_name = instance_name + ".pkl"
		self.load_this_instance ()

	def save_this_instance (self) :
		with open (self.file_name, "wb") as file_handle :
			pickle.dump (self.__dict__, file_handle)

	def load_this_instance (self) :
		try :
			with open (self.file_name, "rb") as file_handle :
				self.__dict__ = pickle.load (file_handle)
		except EOFError as eof_error :
			# print (eof_error)
			pass

if __name__ == "__main__" :
	tester = Self_Saving_Class ("tester")
Now, add these lines to whatever program or programs will use the object. It will attempt to load a saved state of itself when it is created as long as the *.pkl file is in the same directory. You could also add a path to wherever that file is kept.

#
# Tester for self saving class instance
#
import self_saving

tester = self_saving.Self_Saving_Class ("tester")

tester.save_this_instance  ()
Reply
#5
[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!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  how to save to multiple locations during save cubangt 1 1,213 Oct-23-2023, 10:16 PM
Last Post: deanhystad
Question Python3 - serial port reload parovelb 4 8,494 Apr-08-2021, 09:18 AM
Last Post: parovelb
  How to save a class object to a file? SheeppOSU 2 4,382 Jun-22-2019, 11:54 PM
Last Post: metulburr
  Reload module CoolSchoolBoy 3 3,946 Sep-28-2017, 08:31 PM
Last Post: nilamo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020