visual studio portable para online hacer gui debugger debug como code python debugging pdb

python - studio - Adjuntando un proceso con pdb



python debugger portable (2)

Tengo un script en python que sospecho que hay un punto muerto. Estaba tratando de depurar con pdb pero si voy paso a paso, no se produce el interbloqueo, y por la salida devuelta puedo ver que no se cuelga en la misma iteración. Me gustaría adjuntar mi script a un depurador solo cuando se bloquea, ¿es posible? Estoy abierto a usar otros depuradores si es necesario.


En este momento, pdb no tiene la capacidad de detener y comenzar a depurar en un programa en ejecución. Tienes algunas otras opciones:

GDB

Puedes usar GDB para depurar en el nivel C. Esto es un poco más abstracto porque está hurgando en el código fuente C de Python en lugar de en su script de Python real, pero puede ser útil para algunos casos. Las instrucciones están aquí: https://wiki.python.org/moin/DebuggingWithGdb . Están demasiado involucrados para resumir aquí.

Extensiones y módulos de terceros

El solo googlear para "pdb attach process" revela un par de proyectos para darle a PDB esta capacidad:
Pyringe: https://github.com/google/pyringe
Pycharm: https://blog.jetbrains.com/pycharm/2015/02/feature-spotlight-python-debugger-and-attach-to-process/
Esta página del wiki de Python tiene varias alternativas: https://wiki.python.org/moin/PythonDebuggingTools

Para su caso de uso específico, tengo algunas ideas para las soluciones:

Señales

Si estás en Unix, puedes usar signals como en esta publicación de blog para intentar detener y adjuntar a un script en ejecución.

Este bloque de cotización se copia directamente de la publicación del blog vinculado:

Por supuesto, pdb ya tiene funciones para iniciar un depurador en medio de su programa, especialmente pdb.set_trace (). Sin embargo, esto requiere que sepa dónde desea comenzar la depuración, también significa que no puede dejarlo para el código de producción.

Pero siempre he tenido envidia de lo que puedo hacer con GDB: simplemente interrumpa un programa en ejecución y comience a hurgar con un depurador. Esto puede ser útil en algunas situaciones, por ejemplo, estás atrapado en un bucle y quieres investigar. Y hoy se me ocurrió repentinamente: ¡simplemente registre un controlador de señal que establece la función de rastreo! Aquí el código de prueba de concepto:

import os import signal import sys import time def handle_pdb(sig, frame): import pdb pdb.Pdb().set_trace(frame) def loop(): while True: x = ''foo'' time.sleep(0.2) if __name__ == ''__main__'': signal.signal(signal.SIGUSR1, handle_pdb) print(os.getpid()) loop()

Ahora puedo enviar SIGUSR1 a la aplicación en ejecución y obtener un depurador. ¡Encantador!

Me imagino que podría mejorar esto usando Winpdb para permitir la depuración remota en caso de que su aplicación ya no esté conectada a un terminal. Y el otro problema que tiene el código anterior es que parece que no se puede reanudar el programa después de que se invocó a pdb, después de salir de pdb, simplemente se obtiene un rastreo y se realiza (pero como esto es solo bdb, se genera la excepción bdb.BdbQuit, supongo Esto podría resolverse de varias maneras). El último problema inmediato es ejecutar esto en Windows, no sé mucho sobre Windows pero sé que no tienen señales, así que no estoy seguro de cómo podría hacer esto allí.

Puntos de interrupción condicionales y bucles

Es posible que aún pueda usar el PDB si no tiene señales disponibles, si ajusta sus adquisiciones de bloqueo o semáforo en un bucle que incremente el contador, y solo se detenga cuando el recuento haya alcanzado un número ridículamente grande. Por ejemplo, digamos que tiene un bloqueo que sospecha que es parte de su punto muerto:

lock.acquire() # some lock or semaphore from threading or multiprocessing

Vuelve a escribirlo de esta manera:

count = 0 while not lock.acquire(False): # Start a loop that will be infinite if deadlocked count += 1 continue # now set a conditional breakpoint here in PDB that will only trigger when # count is a ridiculously large number: # pdb> <filename:linenumber>, count=9999999999

El punto de interrupción debe activarse cuando el recuento sea muy grande, (esperemos) indicando que se ha producido un punto muerto allí. Si descubre que se está activando cuando los objetos de bloqueo no parecen indicar un interbloqueo, es posible que deba insertar un breve retardo en el bucle para que no se incremente tan rápido. También es posible que tenga que jugar con el umbral de activación del punto de interrupción para que se dispare en el momento adecuado. El número en mi ejemplo era arbitrario.

Otra variante de esto sería no usar PDB e intencionalmente generar una excepción cuando el contador se vuelve enorme, en lugar de desencadenar un punto de interrupción. Si escribe su propia clase de excepción, puede usarla para agrupar todos los estados locales de semáforo / bloqueo en la excepción, luego capturarla en el nivel superior de su script para imprimir justo antes de salir.

Indicadores de archivo

Una forma diferente de usar su bucle sin interbloqueo sin confiar en que los contadores sean correctos sería escribir en los archivos:

import time while not lock.acquire(False): # Start a loop that will be infinite if deadlocked with open(''checkpoint_a.txt'', ''a'') as fo: # open a unique filename fo.write("/nHit") # write indicator to file time.sleep(3) # pause for a moment so the file size doesn''t explode

Ahora deja que tu programa se ejecute por un minuto o dos. Matar el programa y pasar por esos archivos de "punto de control". Si Deadlock es responsable de su programa bloqueado, los archivos que tienen la palabra "hit" escrita en ellos muchas veces indican qué adquisiciones de bloqueos son responsables de su punto muerto.

Puede ampliar la utilidad de esto al tener las variables de impresión en bucle u otra información de estado en lugar de solo una constante. Por ejemplo, usted dijo que sospecha que el interbloqueo está ocurriendo en un bucle pero no sabe en qué iteración se encuentra. Haga que este bucle de bloqueo descargue las variables de control de su bucle u otra información de estado para identificar la iteración en la que se produjo el interbloqueo.


Existe un clon de pdb, llamado imaginativamente pdb-clone , que puede adjuntarse a un proceso en ejecución .

Simplemente agregue from pdb_clone import pdbhandler; pdbhandler.register() from pdb_clone import pdbhandler; pdbhandler.register() al código del proceso principal, y luego puede iniciar pdb con pdb-attach --kill --pid PID .