The Secret Life of Python - The Uncopyable (deepcopy)

Published: (February 25, 2026 at 11:00 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

When deepcopy fails: why some Python objects can’t be cloned

Audio edition: AI podcast on YouTube
Video edition: 7‑minute visual explainer on YouTube

The story

Timothy thought he had mastered Python’s deepcopy. He tried to back up his tournament database by deep‑copying the entire Connection object.

“I deep‑copied the database connection,” he told Margaret.
“But Python just… exploded.”

The traceback ended with:

TypeError: cannot pickle '_thread.lock' object

Why deepcopy mentions pickling

deepcopy works by pickling an object internally – converting it to a byte stream and then reconstructing it. This works for pure data structures, but it fails for objects that represent live resources (e.g., file handles, sockets, thread locks). Those resources are tied to the operating system and cannot be serialized into a portable byte stream.

A database connection, a file handle, or a network socket isn’t just data; it’s a live link to something outside of Python.

Data vs. Resources

CategoryExamplesdeepcopy outcome
Pure DataLists, dicts, custom info classes✅ Works
ResourcesFiles, DB connections, sockets, thread locks❌ Fails

The right way: use a Builder/Factory

Instead of cloning the live object, recreate it from its configuration.

# The WRONG way (crashes)
# backup_conn = copy.deepcopy(original_conn)

# The RIGHT way (Builder)
def create_connection(config):
    """Create a fresh database connection from a config dict."""
    return database.connect(config)

db_config = {"host": "localhost", "user": "admin"}

conn1 = create_connection(db_config)
conn2 = create_connection(db_config)

“You copy the config (the map), not the connection (the journey).”

High‑level warning

Is it pure Data?deepcopy works.
Is it a Resource?deepcopy fails; use a builder/factory.

Advanced note

Objects can define their own __deepcopy__ method to handle custom copying logic, but for system resources it is almost always safer to create a fresh instance rather than trying to clone the existing one.

Takeaway

Even the “ultimate” cloning tool has limits. The best engineers choose the right tool for the material they’re working with.

Next episode teaser: Margaret and Timothy will explore “The Default Trap” – why giving a function a mutable default argument (like a list) is a bad idea.

0 views
Back to Blog

Related posts

Read more »

Reverse array in groups

Problem Statement Reverse an array in groups of a given size k. The array is divided into consecutive chunks windows of length k, and each chunk is reversed in...