Saving class including a container with pickle I am writing a program that has a 'base' class called Group. The class will have only one instance. Aside from some properties and methods, it needs to keep track of a variable amount of group_companies.
After working with the program (that may involve adding or deleting group_companies), I want to save the current state of my work to a file, which can be imported in the next session. I read that pickle can be used for that and even for 'pickling' classes. I have seen similar questions but none answering my question, or yet too complicated for me to be understood.
I came up with the following solution hereunder that seems to work.
Is there a better approach than my solution? I tried to define the group_companies as a class variable, but then it won't 'unpickle' (the group_companies dictionary remains empty).
The next step will involve changing the group_companies from dictionaries to classes themselves. Will that still work?
That you for your help and insights.
import pickle


class Group():
    &quot;&quot;&quot; Creates a group, its metadata and its methods. &quot;&quot;&quot;

    def __init__(self, name, rates):
        self.name = name
        self.rates = rates

    def add_group_company(self, name, descriptor):
        try:
            self.group_companies[name] = descriptor
        except Exception:
            self.group_companies = {}
        self.group_companies[name] = descriptor

    def __repr__(self):
        return &quot;This is group {}&quot;.format(self.name)

# Initialize some variables
group_name = 'XYZ'
rates = {'EUR': 1.0000,
         'USD': 1.2364,
         'NOK': 8.3254,
         }

# Create a group and add some group_companies
group = Group(group_name, rates)
group.add_group_company('ABC', 'some data')
group.add_group_company('DEF', 'moar data')


# pickle the class
with open('data', 'wb') as f:
    pickle.dump(group, f)

# Delete class instance and test if succesfully deleted
del(group)
try:
    print(group)
except Exception:  # catchall
    print(&quot;Variable appears no longer to exist.&quot;)

# Unpickle my class
with open('data', 'rb') as f:
    group = pickle.load(f)

# Test the results (satisfactory)
print(group)
print(group.group_companies)
The pickle module is fine for such a use case, you just have to be
aware of its limitations.
In particular you'd run into problems in case the current class
definition doesn't match the one of the stored object any more, even
something like a renaming of the class is problematic.

Is there a better approach than my solution? I tried to define the
group_companies as a class variable, but then it won't 'unpickle'
(the group_companies dictionary remains empty).

Well, unless you meant to do a class variable it's fine as it is.  At a
glance I wouldn't expect that pickle on an object of a class would
write out class properties anyway, so this all seems like it should
be.  (It wouldn't make sense to write out class properties every single
time an object that's simply an instance of the class is being pickled,
not to mention reading that data back in every single time.)

The next step will involve changing the group_companies from
dictionaries to classes themselves. Will that still work?

Presumably you'd create a Company class and add that to the
dictionary?  That'd work.  Or if you mean you'd change group_companies from a
dictionary to an object, yes, sure, that will work fine as long as the
pickle module understands the objects (which it will in this case).
That said, the code looks fine.  Two small things I'd perhaps change:

Consider using __str__ instead of __repr__ and the difference in
output between group and print(group) in the REPL
(This is group XYZ and &lt;__main.Group object at 0x...&gt; for the
__str__ variant).  repr should return the &quot;canonical string
representation of the object.  [...] eval(repr(obj)) == obj.&quot;  That's
a good guideline for how it should behave, while str is simply for
the printed representation of the object (my words, couldn't find a
quote quickly).

self.group_companies should be initialised from the start in
__init__.  This simplifies add_group_company greatly and will
ensure the object is already in a &quot;valid&quot; state from the start.


Btw. del is a statement, so del group is a bit more explicit in what
it does, removing the group name from the local variable bindings.