Skip to main content

How to Compare Two Dictionaries in Python

Comparing dictionaries is a common task in Python, whether you're validating configurations, tracking data changes, writing tests, or synchronizing records. Python dictionaries can be compared for equality, checked for specific differences, or analyzed to find exactly which keys and values changed.

In this guide, you'll learn multiple methods to compare two dictionaries in Python, from simple equality checks to detailed difference analysis with practical examples.

Using the == Operator (Simplest Method)

The most straightforward way to compare two dictionaries is the == operator. It returns True if both dictionaries have the same keys and the same values, regardless of insertion order.

d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'c': 3, 'a': 1, 'b': 2}
d3 = {'a': 1, 'b': 99, 'c': 3}

print(d1 == d2) # Same content, different order
print(d1 == d3) # Different value for key 'b'

Output:

True
False

Python dictionaries compare by content, not insertion order, so d1 == d2 returns True even though the keys were defined in a different sequence.

tip

The == operator also works with nested dictionaries. It recursively compares all keys and values at every level:

d1 = {'user': {'name': 'Alice', 'age': 30}}
d2 = {'user': {'name': 'Alice', 'age': 30}}

print(d1 == d2) # True

Finding Specific Differences

While == tells you whether dictionaries differ, it doesn't tell you what differs. Here are several ways to identify the exact differences.

Finding Added, Removed, and Changed Keys

Use set operations on dictionary keys to categorize differences:

d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 2, 'c': 99, 'd': 4}

keys_1 = set(d1.keys())
keys_2 = set(d2.keys())

added = keys_2 - keys_1
removed = keys_1 - keys_2
common = keys_1 & keys_2
changed = {k for k in common if d1[k] != d2[k]}
unchanged = {k for k in common if d1[k] == d2[k]}

print(f"Added: {added}")
print(f"Removed: {removed}")
print(f"Changed: {changed}")
print(f"Unchanged: {unchanged}")

Output:

Added:     {'d'}
Removed: {'a'}
Changed: {'c'}
Unchanged: {'b'}

This approach gives you a clear breakdown of exactly what changed between the two dictionaries.

Building a Reusable Diff Function

For production code, wrap the comparison logic into a reusable function:

def dict_diff(d1, d2):
"""Compare two dictionaries and return detailed differences."""
keys_1, keys_2 = set(d1), set(d2)

return {
'added': {k: d2[k] for k in keys_2 - keys_1},
'removed': {k: d1[k] for k in keys_1 - keys_2},
'changed': {
k: {'old': d1[k], 'new': d2[k]}
for k in keys_1 & keys_2 if d1[k] != d2[k]
},
'unchanged': {k: d1[k] for k in keys_1 & keys_2 if d1[k] == d2[k]}
}


config_v1 = {'host': 'localhost', 'port': 8080, 'debug': True, 'log_level': 'INFO'}
config_v2 = {'host': 'localhost', 'port': 9090, 'debug': False, 'workers': 4}

diff = dict_diff(config_v1, config_v2)

for category, items in diff.items():
if items:
print(f"\n{category.upper()}:")
for key, value in items.items():
print(f" {key}: {value}")

Output:

ADDED:
workers: 4

REMOVED:
log_level: INFO

CHANGED:
debug: {'old': True, 'new': False}
port: {'old': 8080, 'new': 9090}

UNCHANGED:
host: localhost

Using a Loop for Manual Comparison

For simple scripts or when you want full control over the comparison logic, a manual loop works well:

d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'a': 1, 'b': 2, 'c': 3}

def are_dicts_equal(dict1, dict2):
"""Check if two dictionaries are equal using manual iteration."""
if len(dict1) != len(dict2):
return False
for key in dict1:
if key not in dict2 or dict1[key] != dict2[key]:
return False
return True

print(are_dicts_equal(d1, d2))

Output:

True

How it works:

  1. First, check if the lengths differ. If they do, the dictionaries can't be equal.
  2. Iterate through each key in dict1 and verify it exists in dict2 with the same value.
  3. If any mismatch is found, return False immediately. If the loop completes, return True.
note

This approach is functionally equivalent to == for flat dictionaries. However, it won't handle nested dictionaries correctly unless you add recursive logic. For nested structures, prefer == or DeepDiff.

Using DeepDiff for Complex Comparisons

For nested dictionaries, large data structures, or cases where you need detailed reports, the third-party deepdiff library is extremely powerful:

pip install deepdiff
from deepdiff import DeepDiff

d1 = {
'user': {
'name': 'Alice',
'settings': {'theme': 'dark', 'language': 'en'}
},
'version': 1
}

d2 = {
'user': {
'name': 'Alice',
'settings': {'theme': 'light', 'language': 'en', 'notifications': True}
},
'version': 2
}

diff = DeepDiff(d1, d2)

for change_type, details in diff.items():
print(f"\n{change_type}:")
for key, value in details.items():
print(f" {key}: {value}")

Output:

values_changed:
root['user']['settings']['theme']: {'new_value': 'light', 'old_value': 'dark'}
root['version']: {'new_value': 2, 'old_value': 1}

dictionary_item_added:
root['user']['settings']['notifications']: True
note

DeepDiff automatically handles nested structures, lists, sets, and other complex data types, providing precise paths to every change.

Comparing Only Specific Keys

Sometimes you only care about certain keys, not the entire dictionary:

def compare_keys(d1, d2, keys):
"""Compare two dictionaries on specific keys only."""
results = {}
for key in keys:
val1 = d1.get(key)
val2 = d2.get(key)
results[key] = {
'equal': val1 == val2,
'values': (val1, val2)
}
return results


user_v1 = {'name': 'Alice', 'age': 30, 'email': 'alice@old.com', 'role': 'user'}
user_v2 = {'name': 'Alice', 'age': 31, 'email': 'alice@new.com', 'role': 'admin'}

# Only compare name and age
result = compare_keys(user_v1, user_v2, ['name', 'age'])

for key, info in result.items():
status = "✅ same" if info['equal'] else f"❌ changed: {info['values'][0]}{info['values'][1]}"
print(f" {key}: {status}")

Output:

  name: ✅ same
age: ❌ changed: 30 → 31

Comparing Dictionaries with Different Key Sets

Common Pitfall: Missing Keys

The == operator correctly handles dictionaries with different key sets. They are simply not equal:

d1 = {'a': 1, 'b': 2}
d2 = {'a': 1, 'b': 2, 'c': 3}

print(d1 == d2) # False: d2 has an extra key

Output:

False

However, if you're comparing value by value using a loop, forgetting to check for extra keys in the second dictionary is a common mistake:

d1 = {'a': 1, 'b': 2}
d2 = {'a': 1, 'b': 2, 'c': 3}

# ❌ Wrong: only checks keys in d1, ignores extra keys in d2
def broken_compare(d1, d2):
for key in d1:
if d1[key] != d2.get(key):
return False
return True

print(broken_compare(d1, d2)) # True: incorrectly ignores 'c' in d2

Output:

True

Always check that both dictionaries have the same number of keys before iterating, or check keys from both sides.

Quick Comparison of Methods

MethodDetects DifferencesShows DetailsHandles NestingExternal Dependency
== operator✅ Equal or notNone
Set operations on keys✅ Added/removed/changedNone
dict_diff() function✅ Full categorization❌ (flat only)None
Manual loop✅ Equal or not❌ (without recursion)None
DeepDiff✅ Full categorization✅ Detailed pathsdeepdiff

Conclusion

Python provides several ways to compare dictionaries depending on what level of detail you need:

  • == operator is the simplest and most efficient way to check if two dictionaries are identical. It handles nested structures and is order-independent.
  • Set operations on keys let you categorize differences into added, removed, changed, and unchanged keys without any external libraries.
  • A reusable diff function provides structured output suitable for logging, reporting, or further processing.
  • DeepDiff is the best choice for complex nested dictionaries where you need precise change paths and detailed reports.

For most everyday comparisons, == is all you need. When you need to know what changed, not just whether something changed, use set operations or DeepDiff to get actionable details.