Solución:
(Desarrollador de Spyder aquí) Somos conscientes de que la experiencia de depuración en Spyder está lejos de ser ideal. Lo que ofrecemos en este momento es muy similar al depurador estándar de Python, pero estamos trabajando para mejorar las cosas en nuestra próxima versión principal para proporcionar algo más cercano a lo que cualquier científico esperaría de un depurador (en resumen, una consola normal de IPython que permite inspecciona y traza las variables en el punto de interrupción actual).
Ahora sobre tus puntos:
-
Es cierto. Estamos pensando en mejorar eso para que si el usuario presiona el botón Ejecutar y hay un punto de interrupción presente en el archivo actual, entonces Spyder entra en modo de depuración y ejecuta el programa hasta que se alcanza el primer punto de interrupción.
-
ipdb
es la consola del depurador de IPython. Desafortunadamente, debido a las limitaciones en la arquitectura de IPython, es muy limitado (no se completa el código ni se examina el historial con flechas). Además, no es posible ejecutar código Python arbitrario en ninguno de los dosipdb
o un regularpdb
consola. Los comandos que puedes ejecutaripdb
son los que puede leer al evaluar elhelp
comando dentro de él. -
Eso es porque, como dije, no se puede evaluar código Python arbitrario.
-
Necesita poner nuevos puntos de interrupción en nuestro Editor para que estén sincronizados con nuestras consolas Python / IPython
Flujo de trabajo de depuración
Debe comprender que, de hecho, está utilizando una integración diferente del depurador de Python pdb
y ipdb
(que usa pdb
y al que se puede acceder mediante el módulo ipdb
). Espero que este ejemplo trivial le ayude a utilizarlo mejor.
Suponga que desea depurar este código:
def Waiting_fun(): #1 line number one
for i in range(100): #2
pass #3
#4
def New_sum(lista, to_s = False): #5
result = 0 #6
print 1 #7
for i in lista: #8
print "summed" #9
result +=i #10
Waiting_fun() #11
if to_s: #12
result = str(result)
return result
a = New_sum([1,4,5,7,8])
b = New_sum([1,4],1)
c = 456
d = New_sum([6,8,9],1)
final_result = a*b*c*d
Out: Type error
Primera depuración rápida usando iPython% debug
%debug
Lo primero que hago es llamar a pdb desde iPython usando el comando mágico %debug
, puede configurarlo como un mecanismo predeterminado usando %pdb
.
%debug
> /home/opdate/Desktop/test.py(23)<module>()
19 a = New_sum([1,4,5,7,8])
20 b = New_sum([1,4],1)
21 c = 456
22 d = New_sum([6,8,9],1)
---> 23 final_result = a*b*c*d
Una vez que almuerces pdb
. Puede encontrar todos los comandos en los documentos oficiales o puede usar el comando h
para mostrarlos. En esta etapa, los únicos comandos que uso son:
-
p
: imprime las variables que especifique -
pp
: bonitos estampados -
args
: si estás dentro de una función imprime los argumentos -
pp locals()
: puede ser útil para imprimir todas las variables, pero la mayoría de las veces es un desastre. -
!
utilícelo si desea evitar conflictos con los comandos enumerados enh
-
whatis
nombre_variable: equivalente al tipo (nombre_variable) -
u
: Mueve el marco actual un nivel hacia arriba en el seguimiento de la pila (a un marco más antiguo). -
d
: Mueve el marco actual un nivel hacia abajo en el seguimiento de la pila (a un marco más nuevo). -
q
: cuando termines puedes usar q para dejar de fumar
En nuestro caso:
ipdb> pp a,b,c,d
(25, '5', 456, '23')
O ipdb> !a,b,c,d
(sin espacio entre el signo de esclavitud y el primer valor). Está claro que byd son cadenas en caso de que podamos usar:
ipdb> whatis b
<type 'str'>
Profundizando usando puntos de ruptura
70% de las veces %debug
le apunta a la solución. Cuando necesite más funciones como puntos de ruptura es hora de usar Spyder. En este caso, queremos entender por qué b
es una cadena, colocamos un punto de interrupción junto a ella (haciendo doble clic junto al número de línea en la ventana del editor). Encuentro mucho mejor para usar la consola estándar de Python en lugar de la consola IPython para la depuración, así que seleccione la consola antes de comenzar a depurar:
Entonces abre el variable explorer
si hay alguna variable elimínela. yo suelo control+F5 para comenzar la depuración, puede usar los botones en la parte superior, pero yo prefiero usar los atajos que se muestran a continuación:
(Pdb) c # we go to the breakpoint
(Pdb) s # we step into the function
(Pdb) args # we see what parameters are inserted
(Pdb) s # going step-by-step
(Pdb) ⏎ # series of Enters go line by line quicker
#Here I'll use whatis command but in fact I just look to
# the type in variable explorer of spyder.
(Pdb) whatis result #check if result is still int
(Pdb) unt #or until -useful to exiting from loops see doc.
(Pdb) n # we don't enter to the Waiting_fun function
(Pdb) s # going step-by-step
(Pdb) whatis result #we find that there the int is converted
(Pdb) j 6 # for double checking we jump back to 6 were the result is assigned
# We may be tempted to j(ump) to line 12 but doing so we would skip all the code
#for avoiding a series of `s`,`unt` and `n` we can use this solution:
(Pdb) tbreak 12 #set a new temporary breakpoint. Also `b` it's ok most of the time
(Pdb) c # go to it
(Pdb) j 6 # we jump to 6 the code we jump is NOT executed
(Pdb) whatis result# we find that if we jump 12-13 result is still int
Ahora hemos localizado el error. También podemos probar una solución repetimos el paso hasta las 12 y ponemos to_s = False
(Pdb) to_s = False #!to_s = False to be on the safe side
Funciona. Una característica importante que utiliza el pdb estándar en el Consola de Python, es que tienes competencia automática y puedes usar el explorador de variables en lugar de usar whatis
y pp
:
Usando el explorador de variables, también puede cambiar el valor de las variables, lo que hace que las cosas sean aún más rápidas.
Puntos de interrupción condicionales
Otra forma más inteligente de localizar el error es utilizar punto de interrupción condicional (Cambio+F12) una gran ventaja de Spyder es depurar y utilizar listas de puntos de interrupción. Los puntos de interrupción condicionales se activan cuando la condición es True
En nuestro caso, queremos ubicar donde b se convierte en una cadena, por lo que la condición es: type(b) == str
. Por lo general, coloco muchos puntos de interrupción condicionales y veo cuáles cumplen la condición. Para hacerlo, no uses Cambio+F12 pero coloque los puntos de interrupción normales haciendo doble clic junto a la línea y vaya a Depurar-> Lista de puntos de interrupción y copie y pase la condición en la tabla a cada punto de interrupción como se muestra en la figura siguiente.
A partir de aquí los comandos a utilizar son:
(Pdb) c # go to the first
(Pdb) u # it helps to understand when it happened
(Pdb) d # come back to the breakpoint
El depurador de pdb funciona bien con pitón regular. Entonces, en Spyder, simplemente cambio a la consola de Python cada vez que quiero depurar de forma interactiva.
import pdb
def yourfunction():
# Interesting stuff done here
pdb.set_trace()
Buena introducción a la depuración con pdb https://pythonconquerstheuniverse.wordpress.com/category/python-debugger/