When you issue pydb myscript.py
you are running pydb
first which then invokes your script myscript.py
via Python's
exec
command. The debugger, pydb
, tries hard to make
itself transparent and thus strips its own program options, resets
sys.argv
and sets __file__
to the values you would get
by calling the debugged program directly.
There may be however some subtle differences. For example the Python
interpreter used would be the one specified by pydb
rather than
possibly that specified inside myscript.py
. Also pydb
does not search your command path, as would be done if issued from a
shell.
Of course you can arrange to get the same interpreter by putting
python
(with the right path) first before pydb
; and you
can give an explicit file path in the script name to debug.
But there are times when even this won't work right.
There is another approach which obviates this complexity and the
attendant drawbacks. However in this approach though you need to
modify your program to add calls to the debugger at special
places. For this, the pydb
function debugger()
can be
used. See 1.3.7. I've even this method to debug the debugger
itself and to debug regression tests.
When pydb.debugger()
is called, the program stops before the
next statement. To continue running the program, issue a debugger
next
, step
or a continue
command.
The exit the program use the quit
or a terminal EOF.
To make this more clear, let's go through an example. Save this in a
file called hardtodebug.py
:
import pydb # some code here def test(): # Force a call to the debugger in running code here pydb.debugger() # ... # ... test() x=5
Now here's a sample run of the program:
python hardtodebug.py a b c --Return-- --Return-- (/tmp/hardtodebug.py:9): (Pydb) list 4 # Force a call to the debugger in running code here 5 pydb.debugger() 6 # ... 7 # ... 8 test() 9 -> x=5 (/tmp/hardtodebug.py:9): (Pydb) restart Re exec'ing ['pydb', 'hardtodebug.py', 'a', 'b', 'c'] (/tmp/hardtodebug.py:1): (Pydb)
The first --Return--
line printed is a result of the
debugger()
exiting. But note that we stopped after the
return from test()
, which explains the second
--Return--
line. Because the next executable statement is after
the implicit return. If you want to stop inside test()
put a
statement after the debugger()
, such as a return
statement. Furthermore, if the program had ended at line 8, then
no stopping would have occurred because the end of the program
is reached first.1.3
Also note that we can issue a restart
which involves some
hackery. But at least in this case it gets things right.
There is one final advantage of using debugger()
. When one is
stepping code or has put a breakpoint in code, the interpreter has to
be involved and calls debugger-checking code written in Python for
every statement that he debugged program runs. And this has a
noticeable effect. With debugger()
there is absolutely no
overhead (provided there are no other breakpoints set in the program).
debugger
above. This
is not hard to code and I've done so, but I'm not sure that doesn't
just confuse things more.