"dictionary changed size during iteration" error in Python 3 but not in Python 2

Cameron Simpson cs at cskk.id.au
Sun Aug 23 05:43:34 EDT 2020


On 23Aug2020 10:00, Chris Green <cl at isbd.net> wrote:
>I have a (fairly) simple little program that removes old mail messages
>from my junk folder.  I have just tried to upgrade it from Python 2 to
>Python 3 and now, when it finds any message[s] to delete it produces
>the error:-
>
>    RuntimeError: dictionary changed size during iteration
>
>I can sort of see why I'm getting the error but have two questions:
>
>1 - Why doesn't it error in Python 2?

The dict internal implementation has changed. I don't know the 
specifics, but it is now faster and maybe smaller and also now preserves 
insert order.

>2 - How do I fix it?

That standard way is to take a copy of what you're iterating over, 
usually just the keys (consumes less memory).

BTW, this approach is standard for _any_ data structure you're iterating 
over and modifying.

So:

    for k, v in d.iteritems():
       ... d.remove(k) ...

might become:

    for k, v in list(d.iteritems()):
       ... d.remove(k) ...

or:

    for k in list(d):
       v = d[k]
       ... d.remove(k) ...

The iterators from iteritems or iterkeys (and plain old items and keys 
in Python 3) walk over the internal structure, which is a hash table. A 
typical dynamic hash table will resize every so often if items are 
inserted or removed, which doesn't just rearrange things, it can reorder 
the keys because the distribution of the keys into buckets can change as 
the number of buckets changes.

Cheers,
Cameron Simpson <cs at cskk.id.au>


More information about the Python-list mailing list