Janet Wang Janet Wang - 5 months ago 16
Python Question

How to pickle class objects into text file and read it back?

if __name__ == "__main__":
h1 = Person(5)
print (h1)


As shown above, I have a object
h1
of class
Person
needed to be saved as text file (.txt). I'm wondering how to fulfill this persistence and read it back?

Some users suggested to use pickle, I think I probably need more detail here.

Answer

Here is a possible solution to get you started. I renamed the person instance name and changed the parameter to a name ;-)

#! /usr/bin/env python
"""Note: Documentation clearly states, that classes can be pickled,
but only iff they "are defined at the top level of a module"."""
from __future__ import print_function

import pickle


class Person(object):
    """Minimal class to showcase (un)pickle."""
    FULL_NAME_DEFAULT = 'N.N.'

    def __init__(self, full_name=None):
        """Detected initializer (show unpickling behaviour)."""
        if full_name is not None:
            self.full_name = full_name
        else:
            self.full_name = self.FULL_NAME_DEFAULT
        print("Initializer called!")
        self.say_hello()

    def say_hello(self):
        """A method to say a personalized hello."""
        print("Hello! My name is '%s'" % (self.full_name,))


def main():
    """Drive the dumps and loads of Person instances."""
    number_one = Person("Jane Awsome")
    print(number_one)
    print("# Serialize the person number_one ... with default protocol:")
    serialized_person = pickle.dumps(number_one)
    print("# Dump of the data representing the serialized_person:")
    print(serialized_person)
    print("# Now for something completely different ...")
    reborn = pickle.loads(serialized_person)
    print("# Back again a copy of number_one, no __init__ called ;-)")
    reborn.say_hello()

if __name__ == "__main__":
    main()

when being run on my machine and with python v2 this results in:

Initializer called!
Hello! My name is 'Jane Awsome'
<__main__.Person object at 0x102e730d0>
# Serialize the person number_one ... with default protocol:
# Dump of the data representing the serialized_person:
ccopy_reg
_reconstructor
p0
(c__main__
Person
p1
c__builtin__
object
p2
Ntp3
Rp4
(dp5
S'full_name'
p6
S'Jane Awsome'
p7
sb.
# Now for something completely different ...
# Back again a copy of number_one, no __init__ called ;-)
Hello! My name is 'Jane Awsome'

Executed with Python v3:

Initializer called!
Hello! My name is 'Jane Awsome'
<__main__.Person object at 0x1010c8780>
# Serialize the person number_one ... with default protocol:
# Dump of the data representing the serialized_person:
b'\x80\x03c__main__\nPerson\nq\x00)\x81q\x01}q\x02X\t\x00\x00\x00full_nameq\x03X\x0b\x00\x00\x00Jane Awsomeq\x04sb.'
# Now for something completely different ...
# Back again a copy of number_one, no __init__ called ;-)
Hello! My name is 'Jane Awsome'

The default protocol has changed I guess :-)

Please try to look up the details you might need for extending and fitting your use case at the normative documentation eg. 12.1. pickle — Python object serialization

... and always take care, when unpickling, if the data might have been tempered with, as you have to rely on your trust what goes in through this channel. It is a powerful one.

So like with JSON and other (de)serializing modules, there are methods optimized for strings, files etc. You can easily read that up in the docs. Here I used dumps() and loads() where the postfix s stands for string.

For output of the content of the serialized person (here in a string variable) to a file and reading back in xou can easily look that up in aforementiioned excellent Python documentation.