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.
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) # Trueimport 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) # TrueSecurity 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.
| Function | Direction | Works with |
|---|---|---|
pickle.dumps(obj)pickle.dumps(obj) | Object → bytes | A bytes object. |
pickle.loads(bytes)pickle.loads(bytes) | bytes → Object | A bytes object. |
pickle.dump(obj, file)pickle.dump(obj, file) | Object → bytes | A binary file. |
pickle.load(file)pickle.load(file) | bytes → Object | A binary file. |
Saving to and loading from a file
Pickle writes binary, so open files in binary mode ("wb""wb" / "rb""rb").
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.5import 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.5What can be pickled?
Pickle handles far more than JSON: nearly all built-in types, plus custom class instances.
| Picklable | Not picklable |
|---|---|
intint, floatfloat, strstr, boolbool, NoneNone | Open file handles |
listlist, tupletuple, dictdict, setset | Network sockets, DB connections |
| Nested combinations of the above | Lambdas (use a named function) |
| Instances of your own classes | Generators / running threads |
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 objectimport 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 objectTo 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.
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]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
| pickle | JSON | |
|---|---|---|
| Output | Binary, Python-only | Text, language-neutral |
| Types | Almost any Python object | Basic types only |
| Human-readable | No | Yes |
| Safe with untrusted data | No | Yes |
| Best for | Caching/state between Python programs | APIs, 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
defdeffunction instead. - Security — never
loadsloads/loadloaddata 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
picklepickleserializes almost any Python object to bytes and back.- Use
dumpsdumps/loadsloadsfor bytes,dumpdump/loadloadfor 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 coffeeWas this page helpful?
Let us know how we did
