Serialization & Pickling
Two long words for one simple idea. Serialization — in Python, pickling — is capturing the state of an object at one moment, so that it can be kept. The object may change afterwards. What you saved does not.
1The two words
Turning a Python object — a list, a dictionary, a number — into a stream of bytes that can be stored in a file.
pickle.dump(object, f)Turning those bytes back into the same object, with the same type and the same values it had when it was saved.
object = pickle.load(f)2What is really being saved: the state
An object has a state — the values it is holding right now. A game is at level 3 with 120 points. A pickle captures that: the state at the instant dump() ran.
Pickling is taking a photograph
This program proves it. The dictionary is pickled, then changed twice — and the file still holds what it held at the start:
import pickle
score = {'player': 'Ravi', 'level': 3, 'points': 120}
f = open('save.dat', 'wb')
pickle.dump(score, f)
f.close()
score['level'] = 7
score['points'] = 450
print('the object now :', score)
f = open('save.dat', 'rb')
saved = pickle.load(f)
f.close()
print('the pickled copy:', saved)the object now : {'player': 'Ravi', 'level': 7, 'points': 450}
the pickled copy: {'player': 'Ravi', 'level': 3, 'points': 120}Change the object as often as you like. The file only ever changes when you press dump().
{'player': 'Ravi', 'level': 3, 'points': 120}Changed 0 times since the file was first written.
{'player': 'Ravi', 'level': 3, 'points': 120}One snapshot, taken when the file was created.
Press play on a few times and watch the right-hand pane refuse to follow.
score has moved on to level 7. The file still says level 3, because that is what was true when dump() ran. A pickle is not a live link to the object — it is a copy of one moment, kept for later.3Several moments, one after another
If one dump() saves one moment, then several dump() calls save several — and what you end up with is a log. Here the same dictionary is pickled three times, at three different values:
import pickle
reading = {'day': 1, 'temperature': 31.5}
f = open('log.dat', 'wb')
pickle.dump(reading, f) # snapshot on day 1
reading['day'] = 2
reading['temperature'] = 33.0
pickle.dump(reading, f) # snapshot on day 2
reading['day'] = 3
reading['temperature'] = 29.5
pickle.dump(reading, f) # snapshot on day 3
f.close()
print('the object at the end:', reading)
print('the log:')
f = open('log.dat', 'rb')
try:
while True:
print(' ', pickle.load(f))
except EOFError:
pass
f.close()the object at the end: {'day': 3, 'temperature': 29.5}
the log:
{'day': 1, 'temperature': 31.5}
{'day': 2, 'temperature': 33.0}
{'day': 3, 'temperature': 29.5}dump() copied the state as it stood at that line. The try/except EOFError loop that reads them back gets its own lesson shortly — here it is only there to show you the log.4Why a program would want this
Every value a program holds dies when the program ends. Pickling is how a program keeps something past that moment — and these are the ordinary reasons for doing it:
You stop playing at level 7 with 450 points and a bag of things you have collected. All of that is one dictionary. Pickle it into save.dat when the player quits, unpickle it next week, and the game carries on exactly where it stopped.
A school program takes attendance today and needs it tomorrow. The list of records goes into a binary file at the end of the run and comes back at the start of the next one — as a list, ready to use, with no rebuilding.
The temperature programme above. Each reading is saved as it was taken, so a month later you can look back at what the value WAS, not only at what it is now.
Save the state before a risky change. If the change turns out badly, unpickle the old state and you are back where you were — the same idea as an undo.
Bytes can travel. One program pickles a dictionary and another program — even on another computer — unpickles it and gets the same dictionary.
5What can be pickled
Everything you have used all year, and anything built out of those pieces:
Nesting is the useful part. A record is a list, a file of records is a list of lists, and pickle handles the whole thing in one call — which is exactly what the rest of this chapter does:
6Saying it the way the paper asks
The process of converting a Python object into a stream of bytes, so that it can be stored in a file. In Python it is done by the pickle module and is called pickling.
The reverse process — converting the stream of bytes stored in a file back into the original Python object. In Python it is called unpickling.
Because everything a program holds is lost when it ends. Pickling stores the object as it is, and unpickling gives it back with its type and values intact, so no rebuilding is needed.
7Recap
Object → bytes, so it can be written to a file. pickle.dump().
Bytes → the same object, with its type and values. pickle.load().
A photograph, not a live link. Change the object afterwards and the file does not follow.
Each call records the object as it stood on that line, so the file keeps a history.
Game saves, records between runs, a log for reference, going back to an earlier state, sending an object elsewhere.
Numbers, strings, lists, tuples, dictionaries, sets — and any nesting of them.
- 1
Pickle a dictionary, change two of its values, then unpickle it and print both.
Hint · The file holds the old values. That is the whole lesson.
- 2
Pickle the same list three times, adding an item in between each one.
Hint · Three snapshots of different lengths, in one file.
- 3
Write down, in your own words, what a program would lose if pickling did not exist.
Hint · Everything it held, every time it ended.
- 4
Think of one program you use that must be saving its state somewhere.
Hint · Anything that remembers where you left off.
What is serialization?
An object is pickled, then changed. What does the file hold?
Which of these is the reverse of pickling?
Why not just save the object in a text file?