Apéndice A
Depuración
En un programa pueden suceder varios tipos de error, y resulta útil distinguirlos para localizarlos rápidamente:
- Python presenta errores de sintaxis mientras traduce el código fuente en código binario. Normalmente indican que hay algo erróneo en la sintaxis del programa. Ejemplo: omitir los dos puntos al final de una sentencia def nos da el mensaje SyntaxError: invalid syntax , algo redundante.
- El sistema de tiempo de ejecución presenta los errores en tiempo de ejecución si algo va mal mientras se ejecuta el programa. La mayoría de los mensajes de error en tiempo de ejecución incluyen información acerca de dónde sucedió el error y qué funciones se estaban ejecutando. Ejemplo: una recursion infinita termina por provocar un error en tiempo de ejecución del “maximum recursion depth exceeded” (superada la profundidad máxima de recursion).
- Los errores semánticos son problemas con un programa que compila y se ejecuta pero no hace lo que se espera de él. Ejemplo: una expresión puede no evaluarse en el orden esperado, dando un resultado inesperado.
El primer paso de la depuración es averiguar con qué tipo de error se enfrenta. Aunque las secciones que siguen están organizadas por tipos de error, algunas técnicas son aplicables en más de una situación.
A.l. Errores de sintaxis
Los errores de sintaxis suelen ser fáciles de arreglar una vez que averigua lo que son. Desgraciadamente, muchas veces los mensajes de error no son muy útiles. Los mensajes más comunes son SyntaxError: invalid syntax y SyntaxError: invalid token , ninguno de los cuales es muy informativo.
Por otra parte, el mensaje le dice en qué lugar del programa sucedió el error. En realidad, le dice dónde notó el problema Python, que no es necesariamente donde está el error. A veces el error está antes de la localización del mensaje de error, muchas veces en la línea anterior.
Si está haciendo el programa incrementalmente, debería tener casi localizado el error. Estará en la última línea que añadió.
Si está usted copiando código de un libro, comience comparando con atención su código con el del libro. Compruebe cada carácter. Al mismo tiempo, recuerde que el libro podría estar equivocado, así que si ve algo que parezca un error de sintaxis, podría serlo.
He aquí algunas formas de evitar los errores de sintaxis más habituales:
- Asegúrese de que no utiliza una palabra clave de Python como nombre de variable.
- Compruebe que tiene los dos puntos al final de la cabecera de todas las sentencias compuestas, las for , while , if , y def .
- Compruebe que el sangrado es consistente. Puede usted sangrar tanto con espacios como con tabuladores, pero es mejor no mezclarlos. Todos los niveles deberían estar anidados por la misma cantidad.
- Asegúrese de que todas las cadenas del código tienen su par de comillas de apertura y cierre.
- Si tiene cadenas que ocupan varias líneas con triples comillas (o triples apóstrofos), asegúrese de que ha terminado la cadena correctamente. Una cadena sin terminar puede provocar un error invalid token al final de su programa, o puede tratar la siguiente parte del programa como una cadena hasta que llegue a la siguiente cadena. ¡En el segundo caso, podría no presentar ningún mensaje de error!
- Un paréntesis sin cerrar — ( , { o [ — hace que Python continue con la línea siguiente como parte de la sentencia actual. Generalmente aparecerá un error casi inmediatamente en la línea siguiente.
- Compruebe el clásico = donde debería haber un == en los condicionales.
Si nada funciona, siga con la sección que sigue…
A.1.1. No consigo ejecutar mi programa, no importa lo que haga.
Si el compilador dice que hay un error pero usted no lo ve, podría ser porque usted y el compilador no miran el mismo código. Compruebe su entorno de programación para asegurarse de que el programa que está editando es el que está intentando ejecutar Python. Si no está seguro, pruebe a poner un error de sintaxis obvio y deliberado al principio del programa. Ahora ejecute (o importe) de nuevo. Si el compilador no encuentra el nuevo error probalemente hay algo equivocado en el modo en que está configurado su entorno.
Si esto ocurre, puede enfrentarse a ello empezando de nuevo con un programa nuevo como “Hola, mundo”, y asegurarse de que puede hacer que funcione un programa conocido. Luego añada gradualmente los trozos del programa nuevo al que funciona.
A.2. Errores en tiempo de ejecución
Una vez que su programa es sintácticamente correcto, Python pude importarlo y al menos comenzar a ejecutarlo. ¿Qué podría ir mal?
A.2.1. Mi programa no hace nada de nada.
Este problema es muy común cuando su archivo consta de funciones y clases pero en realidad no invoca nada para que empiece la ejecución. Esto puede ser intencionado cuando sólo planea importar el módulo para suministrar clases y funciones.
Sin no es intencionado, asegúrese de que está llamando a una función que inicie la ejecución, o ejecute una desde el indicador interactivo. Vea también la sección “Flujo de Ejecución” más adelante.
A.2.2. Mi programa se cuelga.
Si un programa se para y parece no hacer nada, decimos que “se ha colgado”. A menudo significa que se ha quedado atrapado en un bucle infinito o en una recursion infinita.
- Si hay un bucle en particular que le resulta sospechoso de provocar el problema, añada una sentencia print justo antes del bucle que diga “entrando al bucle” y otra inmediatamente después que diga “saliendo del bucle”. Ejecute el programa. Si obtiene el primer mensaje pero el segundo no, tiene usted un bucle infinito. Vaya a la sección “Bucle Infinito” más adelante.
- Una recursion infinita casi siempre hará que el programa corra un rato y luego presente un error de “RuntimeError: Maximum recursion depth exceeded”. Si ocurre eso, vaya a la sección “Recursion Infinita” más adelante. Si no ve este error pero sospecha que hay un problema con un método o función recursivos también puede utilizar las técnicas de la sección “Recursion Infinita”.
- Si no funciona ninguno de estos pasos, comience a probar otros bucles y otros métodos y funciones recursivos.
- Si eso no funciona, es posible que no comprenda el flujo de ejecución de su programa. Vaya a la sección “Flujo de Ejecución” más adelante.
Bucle Infinito
Si cree que tiene un bucle infinito y piensa que sabe qué bucle provoca el problema, añada una sentencia print que imprima los valores de las variables de la condición al final del bucle junto con el valor de la condición.
Por ejemplo:
while x > 0 and y < 0 : hacer algo con x hacer algo con y print "x: ", x print "y: ", y print "condición: ", (x > 0 and y < 0)
Ahora, cuando ejecute el programa, verá tres líneas de salida en cada vuelta del bucle. En la última vuelta el valor de la condición debería ser false . Si el bucle sigue ejecutándose, podrá ver los valores de x e y, y podrá averiguar por qué no se actualizan correctamente.
Recursion Infinita
Una recursion infinita casi siempre hará que el programa se ejecute un rato y luego provoque un error de Maximum recursion depth exceeded .
Si sospecha que una función o un método está causando una recursion infinita, comience por asegurarse de que hay un caso básico. En otras palabras, debería haber una condición que haga que la función devuelva un valor sin hacer otra llamada recursiva. Si no, necesita revisar el algoritmo y encontrar ese caso básico.
Si hay un caso básico pero el programa no parece llegar hasta él, añada una sentencia print que imprima los parámetros al principio de la función o método. Cuando ahora ejecute el programa, verá unas pocas líneas cada vez que se invoque la función o método y allí verá los parámetros. Si los parámetros no se acercan al caso básico, eso le dará alguna idea de por qué no lo hace.