Tengo esta aplicación Python que se atasca de vez en cuando y no puedo averiguar dónde.
¿Hay alguna forma de indicarle al intérprete de Python que le muestre el código exacto que se está ejecutando?
¿Algún tipo de stacktrace sobre la marcha?
Preguntas relacionadas:
Respuestas:
Tengo un módulo que uso para situaciones como esta, donde un proceso se ejecutará durante mucho tiempo pero a veces se atasca por razones desconocidas e irreproducibles. Es un poco hacky, y solo funciona en Unix (requiere señales):
Para usar, simplemente llame a la función listen () en algún momento cuando su programa se inicie (incluso podría pegarlo en site.py para que todos los programas de Python lo usen) y dejarlo correr. En cualquier momento, envíe al proceso una señal SIGUSR1, usando kill o en python:
Esto hará que el programa se rompa a una consola de Python en el punto en el que se encuentra actualmente, mostrándole el seguimiento de la pila y permitiéndole manipular las variables. Use control-d (EOF) para continuar ejecutándose (aunque tenga en cuenta que probablemente interrumpirá cualquier E / S, etc. en el punto que indique, por lo que no es totalmente no intrusivo).
Tengo otro script que hace lo mismo, excepto que se comunica con el proceso en ejecución a través de una tubería (para permitir la depuración de procesos en segundo plano, etc.). Es un poco grande para publicar aquí, pero lo he agregado como una receta de libro de cocina de Python .
fuente
faulthandler
módulo (y su puerto de respaldo que se encuentra en PyPI) para un controlador de señal de nivel C que imprima la pila de Python sin requerir que el bucle de intérprete responda.La sugerencia de instalar un controlador de señal es buena, y la uso mucho. Por ejemplo, bzr por defecto instala un controlador SIGQUIT que invoca
pdb.set_trace()
para colocarlo inmediatamente en un indicador pdb . (Consulte la fuente del módulo bzrlib.breakin para conocer los detalles exactos). Con pdb no solo puede obtener el seguimiento de la pila actual sino también inspeccionar variables, etc.Sin embargo, a veces necesito depurar un proceso en el que no tenía la previsión de instalar el controlador de señal. En Linux, puede adjuntar gdb al proceso y obtener un seguimiento de la pila de Python con algunas macros de gdb. Ponga http://svn.python.org/projects/python/trunk/Misc/gdbinit en
~/.gdbinit
, a continuación:gdb -p
PID
pystack
Desafortunadamente, no es totalmente confiable, pero funciona la mayor parte del tiempo.
Finalmente, adjuntar a
strace
menudo puede darle una buena idea de lo que está haciendo un proceso.fuente
python-dbg
). Sin esos símbolos, parece que no obtienes mucha información útil.Unable to locate python frame
a cada comandoCasi siempre estoy tratando con múltiples subprocesos y el subproceso principal generalmente no está haciendo mucho, por lo que lo más interesante es volcar todas las pilas (que es más como el volcado de Java). Aquí hay una implementación basada en este blog :
fuente
Obtener un seguimiento de la pila de un programa de Python no preparado , que se ejecuta en un stock de Python sin símbolos de depuración se puede hacer con pyrasite . Me funcionó de maravilla en Ubuntu Trusty:
(Un consejo para @Albert, cuya respuesta contenía un puntero a esto, entre otras herramientas).
fuente
dump_stacks.py
simplemente estabaimport traceback; traceback.print_stack()
traceback -l
le brinda una lista de scripts de Python predefinidos que puede usar, ydump_stacks.py
es uno de ellos. Si está utilizando el suyo (por ejemplo, para escribir el seguimiento de la pila en un archivo), podría ser conveniente utilizar un nombre diferente.apt-get install gdb python-dbg
Consejo importante: ejecute (o equivalente) antes de ejecutar pyrasite, de lo contrario fallará silenciosamente. Funciona como un encanto de lo contrario!También puede formatear muy bien el seguimiento de la pila, consulte los documentos .
Editar : para simular el comportamiento de Java, como lo sugiere @Douglas Leeder, agregue esto:
al código de inicio en su aplicación. Luego puede imprimir la pila enviándola
SIGUSR1
al proceso de Python en ejecución.fuente
El módulo de rastreo tiene algunas buenas funciones, entre ellas: print_stack:
fuente
import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
Puedes probar el módulo de manejo de fallas . Instálelo usando
pip install faulthandler
y agregue:Al comienzo de su programa. Luego envíe SIGUSR1 a su proceso (ej .
kill -USR1 42
:) para mostrar el rastreo de Python de todos los hilos a la salida estándar. Lea la documentación para obtener más opciones (por ejemplo, iniciar sesión en un archivo) y otras formas de mostrar el rastreo.El módulo ahora es parte de Python 3.3. Para Python 2, consulte http://faulthandler.readthedocs.org/
fuente
Lo que realmente me ayudó aquí es la sugerencia de spiv (que votaría y comentaría si tuviera los puntos de reputación) para obtener un seguimiento de la pila de un proceso Python no preparado . Excepto que no funcionó hasta que modifiqué el script gdbinit . Entonces:
descargue http://svn.python.org/projects/python/trunk/Misc/gdbinit y póngalo en
~/.gdbinit
editarlo, cambiando[editar: ya no es necesario; el archivo vinculado ya tiene este cambio a partir del 2010-01-14]PyEval_EvalFrame
aPyEval_EvalFrameEx
Adjunte gdb:
gdb -p PID
Obtenga el seguimiento de la pila de Python:
pystack
fuente
No symbol "co" in current context.
Agregaría esto como un comentario a la respuesta de haridsv , pero me falta la reputación para hacerlo:
Algunos de nosotros todavía estamos atascados en una versión de Python anterior a 2.6 (requerida para Thread.ident), por lo que obtuve el código funcionando en Python 2.5 (aunque sin que se muestre el nombre del hilo) como tal:
fuente
python -dv yourscript.py
Eso hará que el intérprete se ejecute en modo de depuración y le dará un rastro de lo que está haciendo el intérprete.
Si desea depurar interactivamente el código, debe ejecutarlo así:
python -m pdb yourscript.py
Eso le dice al intérprete de Python que ejecute su script con el módulo "pdb", que es el depurador de Python, si lo ejecuta así, el intérprete se ejecutará en modo interactivo, al igual que GDB
fuente
Eche un vistazo al
faulthandler
módulo, nuevo en Python 3.3. Unfaulthandler
backport para usar en Python 2 está disponible en PyPI.fuente
En Solaris, puede usar pstack (1) No es necesario realizar cambios en el código de Python. p.ej.
fuente
pstack
que hace lo mismoSi estás en un sistema Linux, utilice la maravilla de
gdb
las extensiones de depuración de Python (puede estar enpython-dbg
opython-debuginfo
paquete). También ayuda con aplicaciones multiproceso, aplicaciones GUI y módulos C.Ejecute su programa con:
Esto instruye
gdb
a prepararpython <programname>.py <arguments>
yr
deshacer.Ahora, cuando el programa se cuelga, cambia a la
gdb
consola, presiona Ctr+Cy ejecuta:Ver sesión de ejemplo y más información aquí y aquí .
fuente
Estuve buscando una solución para depurar mis hilos y la encontré aquí gracias a haridsv. Utilizo una versión ligeramente simplificada que emplea traceback.print_stack ():
Para mis necesidades también filtro hilos por nombre.
fuente
Vale la pena mirar a Pydb , "una versión expandida del depurador de Python basada libremente en el conjunto de comandos gdb". Incluye gestores de señales que pueden encargarse de iniciar el depurador cuando se envía una señal específica.
Un proyecto de Summer of Code 2006 buscó agregar características de depuración remota a pydb en un módulo llamado mpdb .
fuente
Pirateé alguna herramienta que se conecta a un proceso de Python en ejecución e inyecta algo de código para obtener un shell de Python.
Ver aquí: https://github.com/albertz/pydbattach
fuente
pyrasite
funcionó perfectamente!Se puede hacer con excelente py-spy . Es un generador de perfiles de muestreo para programas de Python , por lo que su trabajo es adjuntar a procesos de Python y muestrear sus pilas de llamadas. Por lo tanto,
py-spy dump --pid $SOME_PID
es todo lo que necesita hacer para volcar las pilas de llamadas de todos los hilos en el$SOME_PID
proceso. Por lo general, necesita privilegios escalados (para leer la memoria del proceso de destino).Aquí hay un ejemplo de cómo se ve para una aplicación Python roscada.
fuente
pyringe es un depurador que puede interactuar con la ejecución de procesos de python, imprimir rastros de pila, variables, etc. sin ninguna configuración a priori.
Aunque a menudo he usado la solución de controlador de señal en el pasado, aún puede ser difícil reproducir el problema en ciertos entornos.
fuente
pyrasite
funcionó como un encanto para mí.No hay forma de conectarse a un proceso de Python en ejecución y obtener resultados razonables. Lo que hago si los procesos se bloquean es engancharse e intentar averiguar qué está sucediendo exactamente.
Desafortunadamente, a menudo es extraño el observador que "arregla" las condiciones de carrera para que la salida también sea inútil allí.
fuente
Puede usar PuDB , un depurador de Python con una interfaz de maldiciones para hacer esto. Solo agrega
a su código y use Ctrl-C cuando quiera romper. Puede continuar
c
e interrumpir nuevamente varias veces si se lo pierde y desea intentarlo nuevamente.fuente
Estoy en el campamento de GDB con las extensiones de Python. Siga https://wiki.python.org/moin/DebuggingWithGdb , lo que significa
dnf install gdb python-debuginfo
osudo apt-get install gdb python2.7-dbg
gdb python <pid of running process>
py-bt
También considere
info threads
ythread apply all py-bt
.fuente
Traceback (most recent call first): Python Exception <class 'gdb.error'> No frame is currently selected.: Error occurred in Python command: No frame is currently selected.
cuando se ejecutapy-bt
engdb
?sudo
. Yo también necesitaba corrergdb pyton <pid>
como sudo.Cómo depurar cualquier función en la consola :
Cree la función donde usa pdb.set_trace () , luego la función que desea depurar.
Luego llame a la función creada:
Feliz depuración :)
fuente
No sé de nada similar a la respuesta de Java a SIGQUIT , por lo que es posible que deba compilarlo en su aplicación. ¿Quizás podría hacer un servidor en otro hilo que pueda obtener un seguimiento de pila en respuesta a un mensaje de algún tipo?
fuente
use el módulo de inspección.
stack (context = 1) Devuelve una lista de registros para la pila sobre el marco de la persona que llama.
Lo encuentro muy útil de hecho.
fuente
En Python 3, pdb instalará automáticamente un controlador de señal la primera vez que use c (ont (inue)) en el depurador. Presionando Control-C luego te dejará de nuevo allí. En Python 2, aquí hay una línea que debería funcionar incluso en versiones relativamente antiguas (probado en 2.7 pero revisé la fuente de Python nuevamente a 2.4 y se veía bien):
Vale la pena aprender pdb si pasa algún tiempo depurando Python. La interfaz es un poco obtusa, pero debería ser familiar para cualquiera que haya usado herramientas similares, como gdb.
fuente
En caso de que necesite hacer esto con uWSGI, tiene incorporado Python Tracebacker y solo es cuestión de habilitarlo en la configuración (el número se adjunta al nombre de cada trabajador):
Una vez que haya hecho esto, puede imprimir la traza inversa simplemente conectándose al zócalo:
fuente
En el punto donde se ejecuta el código, puede insertar este pequeño fragmento para ver una traza de pila impresa bien formateada. Se supone que tiene una carpeta llamada
logs
en el directorio raíz de su proyecto.fuente