2008-10-23 17 views
34

Python es bastante bueno, pero desafortunadamente, su depurador no es tan bueno como perl -d.Depurador de Python: entrando en una función que ha llamado interactivamente

Una cosa que hago con mucha frecuencia al experimentar con código es llamar a una función desde dentro del depurador, y entrar en esa función, así:

# NOTE THAT THIS PROGRAM EXITS IMMEDIATELY WITHOUT CALLING FOO() 
~> cat -n /tmp/show_perl.pl 
1 #!/usr/local/bin/perl 
2 
3 sub foo { 
4  print "hi\n"; 
5  print "bye\n"; 
6 } 
7 
8 exit 0; 

~> perl -d /tmp/show_perl.pl 

Loading DB routines from perl5db.pl version 1.28 
Editor support available. 

Enter h or `h h' for help, or `man perldebug' for more help. 

main::(/tmp/show_perl.pl:8): exit 0; 

# MAGIC HAPPENS HERE -- I AM STEPPING INTO A FUNCTION THAT I AM CALLING INTERACTIVELY 
    DB<1> s foo() 
main::((eval 6)[/usr/local/lib/perl5/5.8.6/perl5db.pl:628]:3): 
3:  foo(); 


    DB<<2>> s 
main::foo(/tmp/show_perl.pl:4):  print "hi\n"; 


    DB<<2>> n 
hi 
main::foo(/tmp/show_perl.pl:5):  print "bye\n"; 


    DB<<2>> n 
bye 


    DB<2> n 
Debugged program terminated. Use q to quit or R to restart, 
    use O inhibit_exit to avoid stopping after program termination, 
    h q, h R or h O to get additional info. 

    DB<2> q 

Esto es increíblemente útil cuando se trata de un paso a través el manejo de una función de varias entradas diferentes para descubrir por qué falla. Sin embargo, no parece funcionar ni en pdb ni en pydb (mostraría un ejemplo de python equivalente al anterior, pero da como resultado un gran volcado de la pila de excepciones).

Así que mi pregunta es doble:

  1. Me estoy perdiendo algo?
  2. ¿Hay un depurador de Python que me permita hacer esto?

Obviamente, pude poner las llamadas en el código, pero me encanta trabajar de forma interactiva, por ejemplo. no tener que empezar desde cero cuando quiero intentar llamar con un conjunto ligeramente diferente de argumentos.

+1

¿Puedes aceptar la última respuesta? – sureshvv

+0

OP respondió a su pregunta en la parte inferior: https://stackoverflow.com/a/228653/5512755 – Dunatotatos

Respuesta

29

¡Y he respondido mi propia pregunta! Es el comando "depuración" en pydb:

~> cat -n /tmp/test_python.py 
    1 #!/usr/local/bin/python 
    2 
    3 def foo(): 
    4  print "hi" 
    5  print "bye" 
    6 
    7 exit(0) 
    8 

~> pydb /tmp/test_python.py 
(/tmp/test_python.py:7): <module> 
7 exit(0) 


(Pydb) debug foo() 
ENTERING RECURSIVE DEBUGGER 
------------------------Call level 11 
(/tmp/test_python.py:3): foo 
3 def foo(): 

((Pydb)) s 
(/tmp/test_python.py:4): foo 
4  print "hi" 

((Pydb)) s 
hi 
(/tmp/test_python.py:5): foo 
5  print "bye" 


((Pydb)) s 
bye 
------------------------Return from level 11 (<type 'NoneType'>) 
----------------------Return from level 10 (<type 'NoneType'>) 
LEAVING RECURSIVE DEBUGGER 
(/tmp/test_python.py:7): <module> 
3

No es un depurador de Python que forma parte del núcleo de la distribución de Python llamada 'AP'. Raramente lo uso yo mismo, pero a veces lo encuentro útil.

Teniendo en cuenta este programa:

def foo(): 
    a = 0 
    print "hi" 

    a += 1 

    print "bye" 

foo() 

que aquí hay una sesión de depuración que:

$ python /usr/lib/python2.5/pdb.py /var/tmp/pdbtest.py   ~ 
> /var/tmp/pdbtest.py(2)<module>() 
-> def foo(): 
(Pdb) s 
> /var/tmp/pdbtest.py(10)<module>() 
-> foo() 
(Pdb) s 
--Call-- 
> /var/tmp/pdbtest.py(2)foo() 
-> def foo(): 
(Pdb) s 
> /var/tmp/pdbtest.py(3)foo() 
-> a = 0 
(Pdb) s 
> /var/tmp/pdbtest.py(4)foo() 
-> print "hi" 
(Pdb) print a 
0 
(Pdb) s 
hi 
> /var/tmp/pdbtest.py(6)foo() 
-> a += 1 
(Pdb) s 
> /var/tmp/pdbtest.py(8)foo() 
-> print "bye" 
(Pdb) print a 
1 
(Pdb) s 
bye 
--Return-- 
> /var/tmp/pdbtest.py(8)foo()->None 
-> print "bye" 
(Pdb) s 
--Return-- 
> /var/tmp/pdbtest.py(10)<module>()->None 
-> foo() 
(Pdb) s 
2

Para interactivo, en un código que estoy desarrollando, por lo general les resulta más eficiente para establecer una programación " punto de ruptura "en el código mismo con pdb.set_trace. Esto hace que sea más fácil romper también el estado del programa en un bucle a: if <state>: pdb.set_trace()

+0

Vea también http://stackoverflow.com/questions/150375/how-do-you-break-into-the-debugger -from-python-source-code –

17

También puede depurar interactivamente una función con pdb, siempre que el script que desea depurar no salga() al final:

$ cat test.py 
#!/usr/bin/python 

def foo(f, g): 
     h = f+g 
     print h 
     return 2*f 

Para depurar, iniciar una sesión interactiva de Python y AP importación:

$ python 
Python 2.5.1 (r251:54869, Apr 18 2007, 22:08:04) 
[GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import pdb 
>>> import test 
>>> pdb.runcall(test.foo, 1, 2) 
> /Users/simon/Desktop/test.py(4)foo() 
-> h = f+g 
(Pdb) n 
> /Users/simon/Desktop/test.py(5)foo() 
-> print h 
(Pdb) 

El módulo AP viene con Python y está documentado en la documentación módulos en http://docs.python.org/modindex.html

3

Si está más familiarizado con un depurador GUI, hay winpdb ('win' en este caso no se refiere a Windows). De hecho, lo uso en Linux.

en Debian/Ubuntu:

sudo aptitude install winpdb 

Luego sólo hay que poner esto en su código en el que desea que se rompa:

import rpdb2; rpdb2.start_embedded_debugger_interactive_password() 

A continuación, iniciar Winpdb y adjuntar a su guión en marcha.

+0

Gracias. ¡No estaba enterado de eso! – Ben

+0

Hasta ahora solo funciona para python2.7. https://bugs.launchpad.net/ubuntu/+source/winpdb/+bug/1126411 –

Cuestiones relacionadas