Binary files with pickle
Part of the free LogicWiz Python course, Pack A: CBSE Class 12 Board Pack. The examples and practice run in the app.
Aarav saved his class marks in a text file. Reading them back gave him the string "[101, 'Riya', 88]", not a list, and rec[2] was a bracket, not 88. His teacher said one word: pickle.
You'll learn to
- Open binary files with the modes rb, wb and ab (and their + versions)
- Save any Python object with pickle.dump() and get it back with pickle.load()
- Read every record with the board-favourite loop: load until EOFError
Learn
Why binary files?
A text file stores characters. Save a list in it and you get back a string you have to split and convert.
A binary file with the pickle module stores the Python object itself: lists, dicts, tuples, numbers, all with their types. Turning an object into bytes is called pickling (serialisation); turning bytes back into an object is unpickling.
pickle.dump(obj, f)writes one object.pickle.load(f)reads one object.
The file must be opened in a binary mode: the mode has a b in it.
Text file vs binary file
| Text file (.txt) | Binary file with pickle (.dat) |
|---|---|
| Stores characters you can read in Notepad | Stores bytes; Notepad shows junk |
| You write strings: f.write('91') | You write any object: pickle.dump([1, 'Riya', 91], f) |
| Reading gives text; you split and convert | pickle.load(f) gives back the same list, ints and all |
| Modes r, w, a, r+, w+, a+ | Modes rb, wb, ab, rb+, wb+, ab+ |
dump one record, load it back
import pickle
rec = [101, "Riya", 88.5]
with open("student.dat", "wb") as f: # wb = write binary (creates or wipes)
pickle.dump(rec, f) # object first, file second
with open("student.dat", "rb") as f: # rb = read binary
back = pickle.load(f)
print(back)
print(type(back), back[2] + 1)
The list comes back as a real list: back[2] is the float 88.5, so you can do maths with it straight away.
Many records: load until EOFError
Each dump() adds one object to the file. To read them all you call load() again and again.
There is no "end" marker to check. When load() runs past the last object it raises EOFError (End Of File). So the board pattern is:
- Open the file in
rb. - Inside
try:, loopwhile True:andload()one record at a time. except EOFError:means "all records read"; close the file or justpass.
Write three records, read them all
import pickle
with open("class.dat", "wb") as f:
pickle.dump([1, "Aarav", 91], f)
pickle.dump([2, "Meher", 78], f)
pickle.dump([3, "Kabir", 85], f)
f = open("class.dat", "rb")
try:
while True:
rec = pickle.load(f)
print(rec[1], "scored", rec[2])
except EOFError:
f.close()
Step through it: rec changes three times, and the fourth load() jumps straight to except EOFError.
The classic mistake: forgetting the b
import pickle
with open("oops.dat", "w") as f: # text mode!
pickle.dump([1, "Aarav"], f)
You get TypeError: write() argument must be str, not bytes. Pickle makes bytes, and a text-mode file only accepts str. Use wb.
wb wipes the file. Every time you open with wb, the old records are deleted first. To add records to an existing file, open it with ab (append binary). Use wb only when you create the file from scratch.
Add with ab, read with a counter
import pickle
with open("class.dat", "wb") as f:
pickle.dump({"roll": 1, "name": "Aarav", "marks": 91}, f)
with open("class.dat", "ab") as f: # ab keeps the old record
pickle.dump({"roll": 2, "name": "Meher", "marks": 78}, f)
count = 0
with open("class.dat", "rb") as f:
while True:
try:
rec = pickle.load(f)
except EOFError:
break
count += 1
print(rec["roll"], rec["name"])
print("Records:", count)
Records can be dicts too. This version puts try inside the loop and uses break. Both styles get full marks.
Board marks for a binary-file function: import pickle · the right mode (rb/wb/ab) · a loop with pickle.load() · except EOFError · closing the file (or using with). 1-mark questions ask the argument order: it is pickle.dump(object, file), object first.
In one line
pickle.dump(obj, f) writes one object to a file opened in wb/ab; pickle.load(f) reads one back, so loop until EOFError.