Anexo B
Leer un error de Python
Cometer errores al programar es inevitable, y no es una mala señal: es parte del trabajo. Lo que distingue a quien programa con soltura no es que no se equivoque, sino que sabe leer lo que Python le dice cuando algo falla. Este anexo enseña a leer esos mensajes con los errores más frecuentes al construir la calculadora. Todos los mensajes que se muestran son reales: los produjo el código del libro.
B.1 Cómo se lee un mensaje de error
Supongamos que, al describir una armadura, escribimos por descuido un nodo que no existe: la barra 2 del ejemplo A va al nodo 4, pero la armadura solo tiene tres nodos.
barras_mal = {
1: barra(1, 2, 0.0020),
2: barra(2, 4, 0.0020),
3: barra(3, 1, 0.0020),
}
geometria_mal = calcular_geometria(nodos, barras_mal)
Python se detiene y muestra este mensaje:
Traceback (most recent call last):
File "<celda 44>", line 6, in <module>
geometria_mal = calcular_geometria(nodos, barras_mal)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<celda 9>", line 10, in calcular_geometria
final = nodos[barra["nodo_final"]]
~~~~~^^^^^^^^^^^^^^^^^^^^^
KeyError: 4
El mensaje se llama traza (traceback) y se lee de abajo hacia arriba:
- La última línea dice qué pasó. Primero el tipo de error,
KeyError, y después el detalle: la clave4no existe en el diccionario. - Las líneas anteriores dicen dónde pasó. Cada bloque que empieza con
Filees un paso. El primero es nuestra celda; el segundo, la línea 10 de la función que llamamos,calcular_geometria, que busca el nodo final de cada barra. Los signos~y^subrayan la parte exacta de la línea que falló. - El primer bloque es nuestra celda. Ahí está la línea que escribimos nosotros y que desencadenó el error.
Que el error aparezca dentro de una función no significa que la función esté
mal: casi siempre el problema está en los datos que le dimos. Aquí,
calcular_geometria buscó el nodo final de una barra y no lo encontró,
porque nuestro diccionario barras_mal usa un nodo inexistente.
B.2 Un nombre mal escrito
El error más frecuente de todos es escribir mal un nombre:
geometria = calcular_geometria(nodos, barras)
rigideces = calcular_rigideces(barras, geometira)
Traceback (most recent call last):
File "<celda 45>", line 2, in <module>
rigideces = calcular_rigideces(barras, geometira)
^^^^^^^^^
NameError: name 'geometira' is not defined. Did you mean: 'geometria'?
Python no conoce geometira y, como el nombre se parece a uno que sí
existe, nos sugiere el correcto (Did you mean, ¿quisiste decir?).
Un NameError aparece también cuando usamos una variable o una función
cuya celda no hemos ejecutado: por ejemplo, al abrir de nuevo un notebook,
porque Colab no recuerda nada de la sesión anterior. La solución es ejecutar
las celdas anteriores, o todas con Entorno de ejecución > Ejecutar
todas.
B.3 Errores de escritura
Algunos errores impiden que Python entienda el código, y aparecen antes de que
se ejecute una sola línea. El más común es olvidar los dos puntos al final de
un for, un if o un def:
for numero in barras
print(numero)
File "<celda 46>", line 1
for numero in barras
^
SyntaxError: expected ':'
El mensaje no empieza con Traceback, porque el código no llegó a
ejecutarse: indica la línea y, con el signo ^, el
lugar donde Python esperaba los dos puntos.
El otro error de escritura frecuente es olvidar la sangría del bloque que
sigue a un for:
for numero in barras:
print(numero)
File "<celda 47>", line 2
print(numero)
^^^^^
IndentationError: expected an indented block after 'for' statement on line 1
B.4 Datos equivocados
Si llamamos a una función con menos argumentos de los que necesita, el mensaje dice cuál falta. Aquí olvidamos la longitud de la barra:
k = rigidez_local(2.0e8, 0.0020)
Traceback (most recent call last):
File "<celda 48>", line 1, in <module>
k = rigidez_local(2.0e8, 0.0020)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: rigidez_local() missing 1 required positional argument: 'L'
Un IndexError indica que pedimos una posición que no existe. En la
calculadora casi siempre se debe a confundir la numeración desde 1 con los
índices desde 0. Queremos el desplazamiento vertical del nodo 3, que es el
grado de libertad 6, y lo pedimos con U[6]:
resultados = analizar_armadura(nodos, barras,
apoyos, cargas)
U = resultados["U"]
uy_3 = U[6]
Traceback (most recent call last):
File "<celda 49>", line 4, in <module>
uy_3 = U[6]
~^^^
IndexError: index 6 is out of bounds for axis 0 with size 6
U tiene seis elementos, con índices de 0 a 5. El grado de libertad 6
está en la posición 5, y la forma segura de obtenerla es con la función
indices del capítulo 6.
Una división por cero suele indicar dos nodos con las mismas coordenadas: la barra que los une tiene longitud nula.
nodos_mal = {
1: {"x": 0.0, "y": 0.0},
2: {"x": 6.0, "y": 0.0},
3: {"x": 6.0, "y": 0.0},
}
geometria_mal = calcular_geometria(nodos_mal, barras)
Traceback (most recent call last):
File "<celda 50>", line 6, in <module>
geometria_mal = calcular_geometria(nodos_mal, barras)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<celda 9>", line 15, in calcular_geometria
"c": dx / L, "s": dy / L}
~~~^~~
ZeroDivisionError: float division by zero
B.5 Los errores de la calculadora
Algunos errores los produce la propia calculadora, a propósito, cuando
detecta datos que no tienen solución. Si a la armadura le falta un apoyo,
es singular y resolver_desplazamientos se detiene con un
mensaje propio (capítulo 9):
apoyos_mal = {1: {"x": True, "y": True}}
resultados = analizar_armadura(nodos, barras,
apoyos_mal, cargas)
Traceback (most recent call last):
File "<celda 51>", line 2, in <module>
resultados = analizar_armadura(nodos, barras,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<celda 37>", line 13, in analizar_armadura
U_l = resolver_desplazamientos(
^^^^^^^^^^^^^^^^^^^^^^^^^
File "<celda 24>", line 4, in resolver_desplazamientos
raise ValueError("La armadura es inestable: "
ValueError: La armadura es inestable: K_ll es singular.
La traza recorre tres pasos: nuestra celda llamó a analizar_armadura,
esta llamó a resolver_desplazamientos, y ahí se detectó el problema. El
mensaje está en español porque lo escribimos nosotros.
B.6 Los errores que no avisan
Los errores más peligrosos son los que no producen ningún mensaje: una carga en la unidad equivocada, una coordenada mal escrita o un apoyo en el nodo equivocado dan resultados, pero resultados falsos. Contra ellos solo sirve la verificación: comprobar el equilibrio, comparar el dibujo con la armadura y preguntarse si los números tienen sentido físico, como hicimos a lo largo del libro. La tabla 12.1 del capítulo 12 resume los síntomas más comunes.