Registry / serialization / deepmerge

deepmerge

JSON →
library3.0pypypi✓ verified 26d ago

deepmerge is a Python library providing a toolset for deeply merging Python dictionaries, handling nested structures, lists, and various data types with configurable strategies. The current stable version is 2.0, released recently with Python 3.8+ support. The library maintains a stable API, with new versions focusing on type hints, bug fixes, and minor enhancements.

pip install deepmerge
INSTALL
IMPORT
SIG · DEEPMERGE
D
deepmerge
serializationpythonv3.0
Install
1.6s avg
Import
18ms
Disk
16MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v3.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.018s · 18MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 1.6s · import 0.018s · 18MB
16MB installed
● package 16MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

always_merger
from deepmerge import always_merger
The default, most commonly used merger instance for deep merging dictionaries.
Merger
from deepmerge import Merger
Used to create custom merger instances with specific strategies for different data types.

This example demonstrates how to use the default `always_merger` to combine two dictionaries. Nested dictionaries are merged recursively, and lists are extended by default (elements from the second list are appended to the first). It's crucial to understand that `always_merger.merge(a, b)` modifies `a` in-place, so passing `{}`, `copy.copy(a)`, or `copy.deepcopy(a)` as the first argument is often necessary to prevent unintended side effects on the original dictionary.

from deepmerge import always_merger dict1 = { "name": "Alice", "settings": {"theme": "dark", "notifications": True}, "tags": ["user", "admin"] } dict2 = { "name": "Bob", "settings": {"notifications": False, "language": "en"}, "tags": ["active"] } # By default, always_merger modifies the first dict passed (or a copy). # To keep dict1 unchanged, merge into an empty dict or a deep copy of dict1. merged_dict = always_merger.merge({}, dict1, dict2) print(merged_dict) # Expected output for tags: ['user', 'admin', 'active'] (default list_extend_strategy) # Expected output for settings: {'theme': 'dark', 'notifications': False, 'language': 'en'}
Debug
Known issues
breakingDeepmerge v2.0 dropped support for Python versions older than 3.8. Projects still using Python 3.7 or earlier must pin `deepmerge<2.0`.
fix
Upgrade your Python environment to 3.8+ or pin `deepmerge` to a version prior to 2.0 (e.g., `pip install 'deepmerge<2.0'`).
affects: 2.0+
breakingVersion 2.0 introduced extensive type hinting. While this generally improves static analysis, if you have custom merge strategies or logic that relied on implicit type coercions or incorrect type assumptions, your code might now fail type checks or behave differently when used with type-aware tools like MyPy.
fix
Review any custom merge strategies or type-sensitive code after upgrading. Ensure your custom strategies correctly handle expected input and output types according to the new type hints.
affects: 2.0+
gotchaThe default `always_merger.merge(destination, source1, source2, ...)` modifies the `destination` dictionary in-place. If you intend to preserve the original `destination` dictionary, you must provide a copy (e.g., `always_merger.merge({}, original_dict, new_data)` or `always_merger.merge(copy.deepcopy(original_dict), new_data)`).
fix
Always pass a fresh dictionary (`{}`) or a deep copy (`copy.deepcopy(original_dict)`) as the first argument if the original dictionary must remain unchanged.
affects: all
gotchaThe default list merging strategy for `always_merger` is `list_extend_strategy`, which appends elements from the source list to the destination list. If you expect lists to be overwritten/replaced or merged differently, you need to configure a custom `Merger` instance.
fix
To replace lists, initialize `Merger` with an 'override' strategy for lists: `my_merger = Merger([(list, ['override'])])`. To customize further, define your own list strategy function.
affects: all
breakingIn Deepmerge v2.0+, the `Merger.merge` method (including `always_merger.merge`) no longer accepts multiple source dictionaries. It now expects exactly one destination and one source dictionary. Passing more than two dictionaries (excluding `self`) will result in a TypeError.
fix
To merge multiple dictionaries, chain calls to `merge` or perform merges iteratively. For example, to merge `dict1` and `dict2` into a new dictionary: `merged_dict = always_merger.merge(always_merger.merge({}, dict1), dict2)`.
affects: 2.0+
Errors
Common errors & fixes
AttributeError: 'dict' object has no attribute 'merge'
This error occurs when a user attempts to call a '.merge()' method directly on a standard Python dictionary. Python dictionaries have an `.update()` method for shallow merging, but they do not inherently support the deep merging functionality provided by the `deepmerge` library's `Merger` objects or functions.
fix
To use `deepmerge`, you must import a `Merger` instance (like `always_merger`) or create your own `Merger` object and then call its `.merge()` method. Example: `from deepmerge import always_merger; result = always_merger.merge(base_dict, incoming_dict)`.
TypeError: 'Merger' object is not callable
This error arises when a user tries to call an instance of the `deepmerge.Merger` class directly like a function (e.g., `my_merger(dict1, dict2)`), instead of calling its specific `merge` method.
fix
After creating a `Merger` instance (e.g., `my_merger = Merger(...)`), you need to invoke its `merge` method with the dictionaries you want to merge: `my_merger.merge(base_dict, incoming_dict)`.
deepmerge.exception.InvalidMerge
This exception is raised by the `deepmerge` library when its `Merger` object cannot find an appropriate strategy to resolve a merge conflict between two values, especially when their types differ and no explicit type conflict strategy or fallback strategy has been defined.
fix
When initializing the `Merger` class, provide explicit strategies for handling different data types and type conflicts. For example: `my_merger = Merger([(list, ['append']), (dict, ['merge'])], ['override'], ['override'])` where the last list `['override']` handles type conflicts. This ensures that a rule exists for all merging scenarios.
Upgrade
Version history
3.0latest on PyPI · released Aug 17, 2026
Audit
Dependencies
pythonrequiredRequires Python 3.8 or newer as of deepmerge v2.0.
Agent activity
22 hits · last 30 days
node
18
OpenAI (training)
1
Resources
deepmerge — pip install deepmerge · libregistry