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 NotepadStores 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 convertpickle.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:

  1. Open the file in rb.
  2. Inside try:, loop while True: and load() one record at a time.
  3. except EOFError: means "all records read"; close the file or just pass.

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.