Tecnología · GUÍA PRÁCTICA
¿Python dice “dictionary changed size during iteration”? Demuestra quién cambió el diccionario antes de copiar o bloquear
Separa cambios del mismo bucle, escritores concurrentes, callbacks reentrantes y registros del runtime antes de elegir una reparación verificable.

RuntimeError: dictionary changed size during iteration es una señal de límite: el conjunto de claves cambió mientras alguien recorría el mapping. No identifica si el autor fue el mismo bucle, otro hilo, un callback o un registro de Python o de una dependencia.
Conserva el traceback, demuestra propietario y mutador, elige instantánea, cambio en dos fases, sincronización compartida o corrección upstream, y valida invariantes bajo el entrelazado que fallaba.
1. Conserva el traceback e identifica el mapping
Guarda traceback completo, versiones de Python y paquetes, nombre de hilo o tarea e identidad estable del mapping. Determina si falla tu bucle, deepcopy, weakref, sys.modules, un ejecutor o una dependencia.
Anota si recorres d, keys, values o items y si cambia el conjunto de claves o solo un valor existente; un callback durante esa actualización todavía puede añadir o borrar claves.
2. Reproduce una clase de mutador cada vez
Desactiva callbacks y escritores de fondo. Si aún falla, busca delete, pop, clear, setdefault de clave ausente o inserción en el bucle y sus llamadas. Si solo falla con carga, instrumenta cada ruta de escritura.
Un frame en deepcopy o sorted no prueba que esas funciones mutaran. Callbacks de referencias débiles, limpieza, comparadores, logging, señales o destructores pueden reentrar.
3. Elige instantánea o cambio en dos fases de forma explícita
Si una vista puntual es correcta, usa list(d), list(d.items()), tuple(d) o d.copy() según la semántica. La copia superficial estabiliza claves, no los valores mutables ni lecturas compuestas posteriores.
Si el bucle decide qué cambiar, recopila decisiones sobre una vista estable y aplícalas después. Para consumo destructivo intencional, un bucle popitem documentado expresa mejor el contrato.
4. Haz real la propiedad en concurrencia y reentrada
Con varios hilos, protege lecturas consistentes y todas las escrituras estructurales con el mismo Lock/RLock, o asigna la propiedad a un hilo y usa una cola. Bloquear solo al lector no coordina escritores sin bloqueo.
No llames código desconocido manteniendo un bloqueo arbitrario. Toma una instantánea acotada dentro del límite, libera y llama al callback, o difiere efectos a una segunda fase.
5. Trata registros del runtime como incidentes de dependencia
Si el traceback termina en sys.modules, weakref, ProcessPoolExecutor o un gestor de plugins, reproduce en una versión soportada, revisa el proyecto y conserva caso mínimo y versión corregida.
La aceptación debe forzar el entrelazado antiguo, comprobar claves sin pérdidas ni duplicados, supuestos de orden, callbacks una sola vez y obsolescencia intencional. Solo evitar la excepción no basta.
