Skip to content

Python pickle — Object Serialization

picklepickle converts almost any Python object into a byte stream (serializing / “pickling”) and back again (deserializing / “unpickling”). Use it to save program state, cache results, or pass objects between Python processes.

quickstart.py
import pickle
 
data = {"name": "Ada", "scores": [88, 92], "active": True}
 
blob = pickle.dumps(data)        # object -> bytes
restored = pickle.loads(blob)    # bytes -> object
print(restored)                  # {'name': 'Ada', 'scores': [88, 92], 'active': True}
print(restored == data)          # True
quickstart.py
import pickle
 
data = {"name": "Ada", "scores": [88, 92], "active": True}
 
blob = pickle.dumps(data)        # object -> bytes
restored = pickle.loads(blob)    # bytes -> object
print(restored)                  # {'name': 'Ada', 'scores': [88, 92], 'active': True}
print(restored == data)          # True

Security warning — read this first

Never unpickle data you do not trust. Unpickling can execute arbitrary code, so a malicious pickle file can take over your program. Only load pickles you created yourself or received from a trusted source. For untrusted or cross-language data, use JSON instead.

The four functions

Like jsonjson, picklepickle has a string/bytes pair and a file pair.

FunctionDirectionWorks with
pickle.dumps(obj)pickle.dumps(obj)Object → bytesA bytes object.
pickle.loads(bytes)pickle.loads(bytes)bytes → ObjectA bytes object.
pickle.dump(obj, file)pickle.dump(obj, file)Object → bytesA binary file.
pickle.load(file)pickle.load(file)bytes → ObjectA binary file.

Saving to and loading from a file

Pickle writes binary, so open files in binary mode ("wb""wb" / "rb""rb").

files.py
import pickle
 
model = {"weights": [0.1, 0.2, 0.3], "bias": 0.5}
 
# Save
with open("model.pkl", "wb") as f:
    pickle.dump(model, f)
 
# Load
with open("model.pkl", "rb") as f:
    loaded = pickle.load(f)
 
print(loaded["bias"])   # 0.5
files.py
import pickle
 
model = {"weights": [0.1, 0.2, 0.3], "bias": 0.5}
 
# Save
with open("model.pkl", "wb") as f:
    pickle.dump(model, f)
 
# Load
with open("model.pkl", "rb") as f:
    loaded = pickle.load(f)
 
print(loaded["bias"])   # 0.5

What can be pickled?

Pickle handles far more than JSON: nearly all built-in types, plus custom class instances.

PicklableNot picklable
intint, floatfloat, strstr, boolbool, NoneNoneOpen file handles
listlist, tupletuple, dictdict, setsetNetwork sockets, DB connections
Nested combinations of the aboveLambdas (use a named function)
Instances of your own classesGenerators / running threads
custom_objects.py
import pickle
 
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
 
p = Point(3, 4)
blob = pickle.dumps(p)
p2 = pickle.loads(blob)
print(p2)          # Point(3, 4)
print(p2 is p)     # False -> a brand-new, equal object
custom_objects.py
import pickle
 
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __repr__(self):
        return f"Point({self.x}, {self.y})"
 
p = Point(3, 4)
blob = pickle.dumps(p)
p2 = pickle.loads(blob)
print(p2)          # Point(3, 4)
print(p2 is p)     # False -> a brand-new, equal object

To unpickle a custom class, its class definition must be importable in the program doing the loading.

Protocols

Pickle has several binary protocol versions; higher numbers are more efficient. Use pickle.HIGHEST_PROTOCOLpickle.HIGHEST_PROTOCOL for the best, or pickle.DEFAULT_PROTOCOLpickle.DEFAULT_PROTOCOL for broad compatibility.

protocols.py
import pickle
 
data = list(range(1000))
blob = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
print(len(blob), "bytes")
print(pickle.loads(blob)[:3])   # [0, 1, 2]
protocols.py
import pickle
 
data = list(range(1000))
blob = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
print(len(blob), "bytes")
print(pickle.loads(blob)[:3])   # [0, 1, 2]

pickle vs JSON

pickleJSON
OutputBinary, Python-onlyText, language-neutral
TypesAlmost any Python objectBasic types only
Human-readableNoYes
Safe with untrusted dataNoYes
Best forCaching/state between Python programsAPIs, configs, data exchange

Choose JSON for data shared with other systems or users; choose pickle only for trusted, Python-to-Python data that JSON can’t represent.

Common pitfalls

  • Binary mode required — open files with "wb""wb"/"rb""rb", not "w""w"/"r""r".
  • Cross-version risk — a pickle made in one Python version may not load in another.
  • Lambdas don’t pickle — use a module-level defdef function instead.
  • Security — never loadsloads/loadload data from an untrusted source.

Practice Exercises

Exercise 1 – Round-trip a dictionary

Exercise 2 – Confirm equality after a round-trip

Exercise 3 – Pickle a custom object

Summary

  • picklepickle serializes almost any Python object to bytes and back.
  • Use dumpsdumps/loadsloads for bytes, dumpdump/loadload for binary files.
  • It handles custom classes (the class must be importable to unpickle).
  • Never unpickle untrusted data — it can run arbitrary code; prefer JSON for shared data.
  • Pick pickle for trusted Python-to-Python state; pick JSON for interoperability.

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did