python - escribir - configurar pycharm
Depurador de Python: entrar en una funciĆ³n que ha llamado interactivamente (5)
Python es bastante bueno, pero desafortunadamente, su depurador no es tan bueno como perl -d.
Una cosa que hago muy comúnmente al experimentar con el código es llamar a una función desde dentro del depurador, y paso a 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 intentamos pasar por 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).
Entonces mi pregunta es doble:
- ¿Me estoy perdiendo de algo?
- ¿Hay un depurador de Python que me permita hacer esto?
Obviamente, podría 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.
¡Y respondí mi propia pregunta! Es el comando "depurar" 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>
Hay un depurador de Python que es parte de la distribución principal de python llamada ''pdb''. Raramente lo uso yo mismo, pero a veces lo encuentro útil.
Dado este programa:
def foo():
a = 0
print "hi"
a += 1
print "bye"
foo()
Aquí hay una sesión que lo depura:
$ 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
Para el trabajo interactivo sobre el código que estoy desarrollando, generalmente me resulta más eficiente establecer un "punto de ruptura" programático 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()
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 solo ponga esto en su código donde desea que se rompa:
import rpdb2; rpdb2.start_embedded_debugger_interactive_password()
Luego, inicie winpdb y adjúntelo a su secuencia de comandos en ejecución.
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, inicie una sesión de python interactiva e importe pdb:
$ 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 pdb viene con python y está documentado en los documentos de los módulos en http://docs.python.org/modindex.html