IndentationError en Python: por qué ocurre y cómo evitarlo
El error de sangría que frena a todo el que empieza con Python. Qué significa cada variante, las causas reales, y cómo configurar tu editor para que no vuelva a pasar.
Python te detiene con alguno de estos mensajes:
IndentationError: unexpected indent
IndentationError: expected an indented block
IndentationError: unindent does not match any outer indentation level
Si vienes de otro lenguaje o estás empezando, este error desconcierta, porque el código “se ve bien”. El problema es que en Python la sangría (el espacio al inicio de cada línea) no es estética: es parte de la sintaxis. Vamos a entender cada variante y a dejarlo resuelto para siempre.
Por qué la sangría importa tanto en Python
En la mayoría de lenguajes, los bloques de código se delimitan con llaves { }. Python no las usa: usa la sangría. Todo lo que está indentado bajo un if, un for o una función pertenece a ese bloque. Si la sangría está mal, Python no sabe dónde empieza o termina cada bloque, y se detiene.
Por eso un espacio de más o de menos no es un detalle cosmético: cambia el significado del código o lo rompe.
”expected an indented block”
Significa que abriste un bloque (con :) pero la línea siguiente no está indentada.
def saludar():
print("Hola") # IndentationError: expected an indented block
Después de los dos puntos, Python espera contenido indentado. El arreglo:
def saludar():
print("Hola") # ahora sí, con sangría
Lo mismo aplica tras if, for, while, else, etc. Si pones los dos puntos, la línea siguiente tiene que estar indentada.
”unexpected indent”
Lo contrario: una línea tiene sangría cuando no debería.
print("Hola")
print("Mundo") # IndentationError: unexpected indent
La segunda línea está indentada sin razón, no pertenece a ningún bloque. El arreglo es quitar esa sangría de más:
print("Hola")
print("Mundo")
“unindent does not match any outer indentation level”
Esta es la más confusa, y casi siempre esconde la causa raíz de todas: mezclar espacios y tabuladores.
def procesar():
paso_uno() # esta línea usa espacios
paso_dos() # esta usa un tabulador → error
A simple vista las dos líneas se ven alineadas, pero una usa espacios y la otra un tabulador. Python los trata como cosas distintas, y aunque en pantalla parezcan iguales, para el intérprete no lo son. De ahí que el error sea tan desconcertante: el código “se ve bien” pero no lo está.
La causa raíz: espacios vs tabuladores
El 90% de los IndentationError que parecen imposibles vienen de esto. Copiaste código de una web que usaba tabuladores, tu editor usa espacios, y al mezclarlos todo se rompe aunque se vea perfecto.
La convención oficial de Python (y la recomendación universal) es usar 4 espacios, nunca tabuladores. La buena noticia es que no tienes que contar espacios a mano: se configura el editor una vez y él se encarga.
La solución definitiva: configura tu editor
En VS Code, que es lo más común, haz esto una sola vez y no vuelves a tener el problema:
Abre la configuración (Ctrl + ,) y busca estas opciones:
- “Insert Spaces”: actívala. Hace que la tecla Tab inserte espacios en lugar de un tabulador.
- “Tab Size”: ponla en 4.
Y un truco de rescate cuando ya tienes un archivo con la mezcla: abajo a la derecha en VS Code aparece “Spaces: 4” o “Tab Size”. Haz clic ahí, elige “Convert Indentation to Spaces”, y VS Code convierte todos los tabuladores del archivo a espacios de golpe. Eso arregla de una vez los IndentationError fantasma de un archivo copiado.
Resumen
- expected an indented block → falta sangría tras un
:. Indenta la línea. - unexpected indent → sangría de más. Quítala.
- unindent does not match… → casi siempre espacios mezclados con tabuladores.
- Prevención definitiva: configura tu editor para usar 4 espacios siempre, nunca tabuladores.
Una vez que el editor está bien configurado, el IndentationError prácticamente desaparece de tu vida. Es de esos errores que asustan al principio pero que se eliminan de raíz con dos ajustes.
¿Te sale este error en un archivo que copiaste y no logras ver dónde está la mezcla? Escríbeme desde contacto y lo revisamos.