Python pickle error: cannot pickle object (tested)

TypeError: cannot pickle '_thread.lock' object, PicklingError: Can't pickle <function <lambda>> and Can't get local object all mean pickle met something it can only store by name or not at all. We measured each on Python 3.13.5.

1. What can't be pickled, and the three different exceptions you get

import pickle, threading
def make(): return lambda x: x
items = {"lambda": lambda x: x, "nested lambda": make(), "lock": threading.Lock(),
         "open file": open(__file__), "generator": (i for i in range(3))}
for label, obj in items.items():
    try:
        pickle.dumps(obj)
    except Exception as e:
        print(f"{label:14} {type(e).__name__}: {e}")

Output:

lambda         PicklingError: Can't pickle <function <lambda> at 0x7fa33bd92200>: attribute lookup <lambda> on __main__ failed
nested lambda  AttributeError: Can't get local object 'make.<locals>.<lambda>'
lock           TypeError: cannot pickle '_thread.lock' object
open file      TypeError: cannot pickle 'TextIOWrapper' instances
generator      TypeError: cannot pickle 'generator' object

Measured on Python 3.13.5: pickle stores functions by name, so a lambda (no usable name) fails with PicklingError, while a function defined inside another function fails with AttributeError: Can't get local object. Objects tied to the running process (locks, open files, generators, sockets, database connections) raise TypeError: cannot pickle '...'. Because these are three unrelated exception types, except pickle.PicklingError alone catches only the first one. Catch (pickle.PicklingError, TypeError, AttributeError) if you need to handle all of them.

2. Fix: drop the unpicklable attribute in __getstate__, rebuild it in __setstate__

import pickle, threading
class Worker:
    def __init__(self):
        self.count = 3
        self.lock = threading.Lock()
    def __getstate__(self):
        state = self.__dict__.copy()
        del state["lock"]              # drop what can't be pickled
        return state
    def __setstate__(self, state):
        self.__dict__.update(state)
        self.lock = threading.Lock()   # rebuild it on load
w = pickle.loads(pickle.dumps(Worker()))
print(w.count, type(w.lock).__name__)

Output:

3 lock

Measured: the object pickles and loads with its data (count = 3) and a fresh lock. Use the same pattern for open files (store the path, reopen on load) and connections (store the settings, reconnect). For functions, use a normal module-level def instead of a lambda or nested function, or functools.partial of one. With multiprocessing, the same errors appear when you pass these objects to a pool; see our multiprocessing can't pickle guide. To find which attribute is the problem, try pickle.dumps() on each value in obj.__dict__.

Frequently asked questions

Why do I get TypeError: cannot pickle '_thread.lock' object?

Your object (or something it references) holds a threading.Lock, which belongs to the running process. We measured the error and a fix: remove the lock in __getstate__ and create a new one in __setstate__.

Why can't Python pickle a lambda?

pickle stores functions by their importable name, and a lambda doesn't have one. We measured PicklingError for a module-level lambda and AttributeError: Can't get local object for a nested one.

Does except pickle.PicklingError catch all pickle errors?

No. We measured three different exception types: PicklingError, AttributeError and TypeError.

What objects cannot be pickled in Python?

We measured lambdas, nested functions, locks, open files and generators failing. Sockets and database connections behave the same way: they are tied to the running process.

Written with AI assistance. Measured on 2026-10-09 with Python 3.13.5: pickle.dumps on a lambda, a nested lambda, a threading.Lock, an open file and a generator, and a __getstate__/__setstate__ fix for a class holding a lock. Every block was run verbatim and its output pasted from that run. PlainHeaders is our extension; everything else here is built-in Python.