faulthandler en Python: diagnostica fallos

Publicado el: 27/08/2026
Tempo de leitura: 9 minutos
Close-up view of a computer screen displaying code in a software development environment.

El módulo faulthandler ayuda a diagnosticar fallos graves que pueden terminar un proceso antes de que Python produzca un traceback normal. Puede volcar las pilas cuando ocurre una segmentation fault, abort, bus error, instrucción ilegal, timeout o señal solicitada por un operador. Es especialmente útil en aplicaciones con extensiones nativas, bibliotecas científicas, drivers, bindings, servicios de larga duración, multiprocessing y tests que se bloquean de forma intermitente.

El módulo no corrige el problema y no sustituye un debugger nativo. Su objetivo es conservar contexto suficiente para mostrar dónde estaban las threads de Python cuando el proceso falló o dejó de progresar. Como el runtime puede encontrarse en un estado corrupto, la salida es deliberadamente simple y debe escribirse en un archivo o stream confiable.

Activa faulthandler

La forma más directa es llamar a faulthandler.enable() al inicio de la aplicación.

import faulthandler

faulthandler.enable()

Por defecto, la salida va a sys.stderr. Actívalo antes de cargar extensiones sospechosas o iniciar múltiples threads para capturar fallos tempranos.

Activa mediante variable de entorno

En producción puede ser necesario habilitar el diagnóstico sin cambiar el código.

PYTHONFAULTHANDLER=1 python app.py

Esto resulta práctico en containers, jobs, comandos de test e incidentes. También ayuda cuando el fallo ocurre durante imports antes de que la inicialización normal alcance la configuración.

Usa la opción -X

El intérprete acepta -X faulthandler.

python -X faulthandler app.py

Documenta esta opción en el runbook operativo. Una herramienta de diagnóstico pierde valor si el equipo necesita investigarla durante una caída.

Qué fallos captura

En plataformas compatibles, el módulo instala handlers para señales fatales como SIGSEGV, SIGFPE, SIGABRT, SIGBUS y SIGILL. La disponibilidad exacta depende del sistema operativo y del build de Python.

Estas señales suelen indicar corrupción de memoria, aritmética nativa inválida, abort explícito, dirección incorrecta o instrucción incompatible. El código Python puro rara vez las provoca directamente; las extensiones y bibliotecas externas son sospechosos comunes.

Dump fatal frente a traceback normal

Una excepción Python normal recorre frames, ejecuta bloques finally y puede capturarse. Un fallo nativo fatal puede detener el runtime inmediatamente. Faulthandler intenta escribir las pilas con una implementación restringida que no depende del mecanismo normal de traceback.

El resultado puede omitir variables locales y mostrar únicamente archivos, funciones y líneas. Aun así, esa secuencia suele identificar el subsistema activo.

Escribe en un archivo dedicado

El stderr de un servicio puede perderse, truncarse o mezclarse con muchos logs. Abre un archivo dedicado y mantenlo vivo mientras el handler esté activo.

import faulthandler

archivo = open("fallos-python.log", "a", buffering=1)
faulthandler.enable(file=archivo, all_threads=True)

No cierres el archivo mientras faulthandler pueda utilizarlo. El módulo conserva el descriptor y no abre automáticamente un reemplazo.

Rotación de logs

Si un rotador externo renombra o sustituye el archivo, el descriptor antiguo puede seguir apuntando al inode anterior. Reabre el destino y configura de nuevo el handler, o utiliza stderr y deja que el runtime de containers recoja la salida.

Prueba la estrategia exacta de rotación en el mismo entorno de producción.

Incluye todas las threads

El parámetro all_threads=True incluye todas las threads Python disponibles.

faulthandler.dump_traceback(all_threads=True)

Esto es esencial cuando una thread espera a otra. La thread que solicita el dump puede no ser la responsable del deadlock.

Genera un dump manual

dump_traceback() escribe las pilas sin terminar el proceso.

import faulthandler

faulthandler.dump_traceback()

Úsalo en comandos administrativos protegidos, watchdogs internos y tests controlados. Nunca expongas el dump públicamente porque las rutas y la arquitectura pueden ser sensibles.

Programa un dump por timeout

dump_traceback_later() agenda una captura cuando una operación supera un plazo.

faulthandler.dump_traceback_later(
    30,
    repeat=False,
    file=archivo,
    exit=False,
)
try:
    ejecutar_operacion()
finally:
    faulthandler.cancel_dump_traceback_later()

Este patrón es útil para tests que se cuelgan, startup lento, shutdown bloqueado y llamadas nativas que no vuelven.

Repite los dumps

Con repeat=True, el módulo escribe pilas en intervalos sucesivos.

Varias capturas permiten diferenciar un deadlock estático de un proceso lento que todavía progresa. La repetición puede generar mucho volumen, así que define retención y cancela el timer al terminar.

Finaliza después del timeout

El parámetro exit=True solicita una salida inmediata después del dump.

Úsalo únicamente cuando un supervisor pueda sustituir el proceso y continuar sea inseguro. La salida abrupta omite cleanup normal, puede dejar buffers sin flush e interrumpir transacciones.

Registra una señal operativa

En sistemas Unix, register() puede asociar un dump a una señal de usuario.

import faulthandler
import signal

faulthandler.register(
    signal.SIGUSR1,
    all_threads=True,
    chain=False,
)

Un operador autorizado puede enviar la señal al PID y obtener las pilas sin detener el proceso.

Elige la señal con cuidado

No sobrescribas una señal utilizada por la aplicación, servidor, runtime o agente de observabilidad. Documenta la señal y comprueba conflictos.

Dentro de containers, verifica que llegue al proceso Python. Un shell como PID 1 puede no reenviarla.

El parámetro chain

Con chain=True, el handler anterior también se ejecuta después del dump. Esto puede conservar otra herramienta de diagnóstico, pero también activar lógica insegura en contexto de señal.

Prueba la combinación en la misma plataforma y versión desplegada.

Desregistra una señal

unregister(signum) elimina el handler configurado por el módulo.

faulthandler.unregister(signal.SIGUSR1)

Úsalo al descargar plugins, cambiar la estrategia o limpiar tests que modifican señales globales.

Comprueba si está activo

is_enabled() indica si los handlers fatales están habilitados.

if not faulthandler.is_enabled():
    faulthandler.enable()

La comprobación sirve en ejecutables y frameworks. Una biblioteca reutilizable debería dejar la decisión global a la aplicación.

No lo actives ocultamente en bibliotecas

Una biblioteca no debería modificar stderr, señales o archivos globales sin consentimiento. Ofrece una función explícita de configuración.

Los handlers globales pueden entrar en conflicto con notebooks, test runners, servidores e intérpretes embebidos.

Integración con tests

Activa el módulo al ejecutar tests con extensiones nativas, threads o subprocesses.

python -X faulthandler -m pytest

Para un test que puede bloquearse, agenda un timeout algo mayor que la duración esperada. Las pilas suelen señalar el fixture, lock, queue o llamada nativa detenida.

Multiprocessing

Cada proceso posee su propio intérprete y debe activar faulthandler por separado. Un dump del padre no muestra automáticamente las threads de los hijos.

def iniciar_worker():
    faulthandler.enable()

Usa archivos separados por PID o stderr centralizado para evitar salidas mezcladas.

Threads

Los dumps de todas las threads revelan locks, condiciones, queues e I/O bloqueante. Asigna nombres claros a las threads para mejorar logs y debugger.

threading.Thread(
    target=worker,
    name="importador-clientes",
)

Faulthandler se centra en frames, pero el naming consistente mejora el resto de la evidencia.

Concurrent futures

Un pool puede parecer congelado cuando todos los workers esperan otro future del mismo executor. Dumps repetidos muestran muchas threads bloqueadas en Future.result().

Consulta concurrent.futures en Python para prevenir deadlocks estructurales.

Extensiones nativas

Si el último frame Python llama a una extensión, el fallo puede estar en C, C++, Rust, Fortran, runtime de GPU o driver. Registra versiones, arquitectura, sistema operativo, entradas y pasos de reproducción.

La pila Python identifica la frontera, pero quizá necesites GDB, LLDB, WinDbg, sanitizers o herramientas del proveedor.

Pila C cuando está disponible

Versiones y builds recientes pueden ofrecer información adicional de la pila nativa en entornos compatibles. Depende de la plataforma, opciones de compilación y símbolos de debug.

Trata esa salida como complemento. Binarios con símbolos mejoran mucho el diagnóstico.

Lifetime del descriptor

El módulo escribe mediante el descriptor asociado al stream. Si cierras el archivo y ese número se reutiliza, la salida podría dirigirse a otro destino.

Mantén ownership explícito y cierra solamente después de desactivar el handler o finalizar el proceso.

Desactiva cuando sea necesario

disable() elimina los handlers fatales instalados por el módulo.

faulthandler.disable()

Puede ser necesario en tests de handlers propios o aplicaciones embebidas. En servicios normales, mantenerlo activo tiene poco coste.

Seguridad de los dumps

Aunque se omiten muchos valores locales, los dumps pueden revelar rutas, nombres internos, módulos específicos de clientes y arquitectura.

Protege los archivos, limita el acceso a señales, aplica retención y sanitiza antes de publicar un informe.

Privacidad en servicios multi-tenant

Un dump de todas las threads puede mostrar operaciones de varios clientes al mismo tiempo. Trátalo como dato operativo sensible.

No expongas la generación mediante endpoint sin autenticación fuerte, autorización y auditoría.

Watchdogs

Un watchdog externo puede pedir un dump antes de reiniciar un proceso sin respuesta. Esto conserva evidencia y permite recuperación automática.

Usa dos deadlines: primero diagnóstico y después terminación. El proceso tiene oportunidad de volver y el operador obtiene contexto si sigue bloqueado.

Deadlock frente a lentitud

Un dump muestra posición; varios muestran movimiento. Si las líneas cambian, quizá el proceso solo sea lento. Frames idénticos en waits y locks sugieren deadlock o bloqueo permanente.

Combina las pilas con métricas de CPU, I/O, queues, memoria y latencia.

No sustituye logging

Los logs explican la secuencia semántica anterior; faulthandler muestra posiciones en el instante crítico. Utiliza ambos.

Incluye IDs de operación y versiones para relacionar el dump con una request o job.

No sustituye un core dump

Un core dump conserva memoria y estado nativo para análisis profundo, pero es grande y puede contener secretos. Faulthandler es ligero y rápido.

Para incidentes difíciles, configura ambos según la política de seguridad.

Limitaciones

Ningún handler se ejecuta después de SIGKILL, corte de energía o algunas terminaciones inmediatas. Una corrupción severa también puede impedir una salida completa.

El módulo no detecta automáticamente todos los deadlocks ni explica el estado interno de bibliotecas nativas.

Prueba el camino de diagnóstico

No esperes un crash real. Genera dumps manuales en un entorno controlado y verifica destino, permisos, rotación, recogida y alertas.

Repite en containers, systemd, Windows Services y workers separados.

Errores comunes

Los errores frecuentes son activarlo demasiado tarde, cerrar el archivo, creer que un timeout detiene la operación sin exit, registrar una señal en conflicto, exponer dumps, esperar detalles nativos completos y activarlo solo en el padre.

Conclusión

faulthandler es una capa simple y valiosa para diagnosticar crashes, deadlocks y bloqueos. Actívalo pronto, conserva la salida en un destino fiable, usa señales o timeouts y captura todas las threads.

Combina el informe con logs, métricas y debuggers nativos cuando existan extensiones C. Consulta la documentación oficial de faulthandler y dis en Python para inspeccionar bytecode cercano al fallo.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código Python en pantalla representando EnumDict y enumeraciones avanzadas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    EnumDict: personaliza Enums con validación

    Aprende EnumDict en Python para personalizar EnumType, validar miembros y crear enumeraciones avanzadas con seguridad.

    Ler mais

    Tempo de leitura: 4 minutos
    11/10/2026
    Rack de servidores que representa el balanceo de conexiones con SO_REUSEPORT_LB en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    SO_REUSEPORT_LB: reparte conexiones entre workers

    Aprende SO_REUSEPORT_LB en Python para distribuir conexiones entre workers con pruebas, portabilidad y cierre ordenado.

    Ler mais

    Tempo de leitura: 5 minutos
    11/10/2026
    Código Python asíncrono en un portátil para inspect.markcoroutinefunction
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: detecta wrappers async

    Aprende inspect.markcoroutinefunction en Python para identificar wrappers asíncronos, integrar frameworks y evitar detecciones incorrectas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Código Python para recorrer carpetas y archivos con Path.walk
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: recorre directorios con seguridad

    Aprende Path.walk en Python para recorrer directorios, filtrar archivos, tratar errores y controlar la travesía con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Depuración de un proceso Python en terminal con código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depura procesos Python en ejecución

    Aprende a conectar pdb a un proceso Python en ejecución, inspeccionar la pila y diagnosticar bloqueos de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026
    Código Python para representar fracciones exactas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: convierte números en fracciones

    Aprende fractions.from_number en Python para convertir números en fracciones exactas, controlar precisión, validar entradas y evitar redondeos inesperados.

    Ler mais

    Tempo de leitura: 4 minutos
    09/10/2026