Artículo original: New faulthandler module in Python 3.3 helps debugging
Cuando un usuario reporta que tu programa ha fallado o se cuelga, algunas veces sólo puedes ayudar a probar y recoger más información y componer un escenario para reproducir la situación. Incluso con un escenario fidedigno de usuario, como desarrollador muchas veces eres incapaz de reproducir la situación debido a diferencias en el entorno, p. ej., sistema operativo y compilador. Si tienes suerte, el usuario podrá instalar herramientas de depuración, pero la mayoría de las veces tendrás que esperar a que otra persona pueda obtener más información sobre la situación.
Errores fatales
En Python 3.3 se ha introducido un nuevo módulo que te ayudará a resolver este problema: faulthandler. faulthandler proporciona la habilidad de volcar la traza inversa de Python en un error fatal tal como sucede en un fallo de segmento, división por cero, abortado o error de bus. Puedes habilitarlo dentro de tu aplicación usando faulthandler.enable(), incorporando la opción -X faulthandler al ejecutable Python, o con la variable de entorno PYTHONFAULTHANDLER=1. Ejemplo de salida:
Fatal Python error: Segmentation fault Current thread 0x00007f7babc6b700: File "Lib/test/crashers/gc_inspection.py", line 29 in g File "Lib/test/crashers/gc_inspection.py", line 32 in <module> Segmentation fault
Tiempo de espera
faulthandler también puede volcar la traza inversa después de un tiempo de espera usando faulthandler.dump_tracebacks_later(timeout). Llámalo otra vez para reiniciar el temporizador o llama a faulthandler.cancel_dump_tracebacks_later() para parar el temporizador. Ejemplo de salida:
Timeout (0:01:00)! Current thread 0x00007f987d459700: File "Lib/test/crashers/infinite_loop_re.py", line 20 in <module>
Usa la opción repeat=True para volcar la traza inversa cada timeout segundos, o exit=True para salir del programa inmediatamente de forma insegura, p. ej. no volcando el buffer de archivos a disco.
Señal de usuario
Si tienes acceso a la maquina en la cual se está ejecutando el programa, puedes usar faulthandler.register(signal) para instalar un gestor de señal que vuelque la traza inversa cuando se reciba signal. En UNIX, por ejemplo, puedes usar la señal SIGUSR1: kill -USR1 <pid> volcará la traza inversa actual. Esta funcionalidad no está disponible bajo Windows. Ejemplo de salida:
Current thread 0x00007fdc3da74700: File "Lib/test/crashers/infinite_loop_re.py", line 19 in <module>
Otra posibilidad es llamar explícitamente a faulthandler.dump_traceback() en tu programa.
Temas de seguridad y el fichero de salida
faulthandler está deshabilitado por defecto por razones de seguridad, principalmente porque almacena el descriptor de fichero de sys.stderr y escribe las trazas inversas en este descriptor de fichero. Si se cierra sys.stderr y se reusa el descriptor de fichero, este descriptor puede ser un socket, una tubería, un fichero crítico o cualquier otra cosa. Por defecto, faulthandler escribe las trazas inversas en sys.stderr, pero puedes especificar otro fichero. Para más información, consulta la documentación de faulthandler.
Módulo de terceros para versiones antiguas de Python
faulthandler también es mantenido como un módulo de terceros para Python 2.5 hasta 3.2 mediante PyPi. La mayor diferencia entre el módulo Python 3.3 y el módulo de terceros es la implementación de dump_tracebacks_later(): Python 3.3 usa un hilo con un tiempo de espera en un bloqueo, por otro lado el de terceros usa SIGALRM y alarm().
El tiempo de espera del bloqueo (que es una nueva funcionalidad de Python 3.3), tiene una resolución de un microsegundo. El temporizador alarm() usado en versiones anteriores tiene una resolución de un segundo, y la señal SIGALRM puede interrumpir la llamada actual al sistema que fallará con un error EINTR.
Éxito rápido
El nuevo módulo faulthandler ya ha sido de ayuda en el rastreo de condiciones de carrera en nuestros buildbots. Esperamos que te ayude también en tus programas.
No hay comentarios:
Publicar un comentario