How to avoid "RuntimeError: dictionary changed size during iteration" error?

Learn how to avoid "runtimeerror: dictionary changed size during iteration" error? with practical examples, diagrams, and best practices. Covers python, list, dictionary development techniques with...

How to Avoid 'RuntimeError: dictionary changed size during iteration' in Python

Hero image for How to avoid "RuntimeError: dictionary changed size during iteration" error?

Learn why Python's dictionaries throw a RuntimeError when modified during iteration and discover robust strategies to prevent this common issue.

The RuntimeError: dictionary changed size during iteration is a common exception encountered by Python developers. This error occurs when you attempt to modify a dictionary (e.g., add, remove, or change items) while you are actively iterating over it. Python's design philosophy prioritizes predictable behavior and prevents potential inconsistencies that could arise from such modifications, leading to this explicit error.

Understanding the Problem

When you iterate over a dictionary, Python creates an internal view of its items. If the dictionary's size changes during this process, the internal view becomes invalid, and Python raises a RuntimeError to prevent unexpected behavior or data corruption. This is a safety mechanism, not a bug. It applies to direct iteration using for key in dict: or for key, value in dict.items():.

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

for key, value in my_dict.items():
    if key == 'b':
        my_dict['d'] = 4  # This will raise RuntimeError
    print(f"{key}: {value}")

Example of code that will cause 'RuntimeError: dictionary changed size during iteration'

flowchart TD
    A[Start Iteration] --> B{Dictionary Modified?}
    B -- Yes --> C["RuntimeError: dictionary changed size during iteration"]
    B -- No --> D[Continue Iteration]
    D --> E{End of Dictionary?}
    E -- No --> A
    E -- Yes --> F[Iteration Complete]

Flowchart illustrating when the RuntimeError occurs during dictionary iteration

Effective Solutions

There are several robust ways to modify a dictionary while iterating, each suited for different scenarios. The key is to avoid direct modification of the dictionary being iterated.

1. Iterate Over a Copy

The simplest and often most straightforward solution is to iterate over a copy of the dictionary's keys, values, or items. This allows you to safely modify the original dictionary without affecting the iteration process.

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

# Iterate over a copy of keys
for key in list(my_dict.keys()):
    if key == 'b':
        my_dict['d'] = 4  # Safe to add
    elif key == 'c':
        del my_dict[key]  # Safe to delete
    print(f"Processing key: {key}")

print(f"Modified dictionary: {my_dict}")

Modifying a dictionary by iterating over a copy of its keys

2. Build a New Dictionary

If your modifications are complex or involve creating a significantly different structure, it's often cleaner to build a new dictionary based on the original, applying your logic during its construction. This approach is particularly useful when filtering or transforming items.

original_dict = {'apple': 1, 'banana': 2, 'cherry': 3, 'date': 4}
new_dict = {}

for key, value in original_dict.items():
    if value % 2 == 0:  # Keep even values
        new_dict[key] = value
    if key == 'banana': # Add a new item based on a condition
        new_dict['grape'] = 5

print(f"Original dictionary: {original_dict}")
print(f"New dictionary: {new_dict}")

Building a new dictionary with filtered and added items

3. Store Keys for Deletion/Modification

If you only need to delete or modify specific items, you can collect the keys of the items to be acted upon during the first pass, and then perform the actual modifications in a second pass.

my_dict = {'item1': 10, 'item2': 20, 'item3': 30, 'item4': 40}
keys_to_delete = []
keys_to_update = {}

# First pass: identify changes
for key, value in my_dict.items():
    if value > 25:
        keys_to_delete.append(key)
    elif value == 20:
        keys_to_update[key] = value * 2

# Second pass: apply changes
for key in keys_to_delete:
    del my_dict[key]

for key, new_value in keys_to_update.items():
    my_dict[key] = new_value

print(f"Final dictionary: {my_dict}")

Collecting keys for modification in a separate pass