breakpoint versus pdb
Normally we import pdb and then to use the PDB in the program we have to use one of its method named set_trace(). This is how the code goes:
import pdb pdb.set_trace()
An easier alternative (starting from Python version 3.7 onwards) is to use the built-in breakpoint() function. This helps us to do away with explicit import
breakpoint() # in python 3.7 and above
When we call the breakpoint() function, the default implementation of the breakpoint() function will call sys.breakpointhook(), which in turn calls the pdb.set_trace() function. This is why we do not need to import pdb and call pdb.set_trace() explicitly ourselves.
Another advantage of using breakpoint() is that can disable all breakpoints in the code. To achieve the same viz command line (name of program is TestPgm.py)
PYTHONBREAKPOINT=0 python TestPgm.py
Within a python program, we can use the following code to disable all breakpoints.
1 2 3 | # setting the value of the PYTHONBREAKPOINT environment variable import os os.environ['PYTHONBREAKPOINT'] = '0' |
101 of Using a debugger
The purpose of a debugger is to provide us with a mechanism to pause the running of a program at any given point and then peruse the code with the contents of the variables used in the program. To achieve this the debugger provides us with a breakpoint that will kick in when a specific line of code is reached. From this point onward, we can peruse the code line by line.
Debugger parses the code line by line where we add the breakpoint. If a bug is found then the program stops temporarily. We can then remove the error and start to execute the code again. The best thing about the debugger - we can manipulate the variables while we are debugging.
Lets consider a sample program as shown below. Let us save its as TestPgm.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # Program named TestPgm.py def maximum(a, b): # Function to calculate the maximum of two numbers if a >= b: return a else: return b # Main code a = 2 b = 4 z = maximum(a, b) print('The maximum of the two numbers is: {}'.format(z)) |
To run the above program in the command line, we just need to go to the command prompt and type in:
python TestPgm.py
But if we want to run the same program with the python debugger, we run the same program, with the following command.
python -m pdb TestPgm.py
The -m pdb part will load the pdb module and let the module execute the file TestPgm.py When we run this command, we will receive the following prompt:
> c:\users\pavan\onedrive\documents\testpgm.py(79)()
-> def maximum(a, b):
(Pdb)
-> def maximum(a, b):
(Pdb)
At the prompt, we can type in the debugger commands. To get a list of all supported commands, we can use h or type in help. And to show the details of the specific command (such as condition), we can use h condition or we can use help condition
(Pdb) h
Documented commands (type help <topic>):
========================================
EOF c d h list q rv undisplay
a cl debug help ll quit s unt
alias clear disable ignore longlist r source until
args commands display interact n restart step up
b condition down j next return tbreak w
break cont enable jump p retval u whatis
bt continue exit l pp run unalias where
Miscellaneous help topics:
==========================
exec pdb
(Pdb) h condition
condition bpnumber [condition]
Set a new condition for the breakpoint, an expression which
must evaluate to true before the breakpoint is honored. If
condition is absent, any existing condition is removed; i.e.,
the breakpoint is made unconditional.
Usually, the n command is what we use as it executes that line of code and moves the flow at the same level without drilling down deeper. When we are at a line that calls a function, example z = maximum(a, b), we can use s to step into the function.
> c:\users\pavan\onedrive\documents\testpgm.py(13)<module>()
-> z = maximum(a, b)
(Pdb) s
--Call--
> c:\users\pavan\onedrive\documents\testpgm.py(2)maximum()
-> def maximum(a, b):
(Pdb) n
> c:\users\pavan\onedrive\documents\testpgm.py(4)maximum()
-> if a >= b:
(Pdb)
If the program is very long and we want to skip some parts, we can use until command with a line number to let the debugger run the program until that line is reached. One another to use the until command is in conjunction with a breakpoint() just after the line number in the until command.
C:\Users\pavan\OneDrive\Documents>python -m pdb TestPgm.py > c:\users\pavan\onedrive\documents\testpgm.py(2)<module>() -> def maximum(a, b): (Pdb) until 13 > c:\users\pavan\onedrive\documents\testpgm.py(13)<module>() -> z = maximum(a, b) (Pdb)
Another command similar to until is return This will execute the current function until the point that it is about to return. It is equivalent to until with the line number equal to the last line of the current function
> c:\users\pavan\onedrive\documents\testpgm.py(2)maximum() -> def maximum(a, b): (Pdb) n > c:\users\pavan\onedrive\documents\testpgm.py(4)maximum() -> if a >= b: (Pdb) return --Return-- > c:\users\pavan\onedrive\documents\testpgm.py(7)maximum()->4 -> return b (Pdb)
We can place a breakpoint with a condition so that it will stop only if the condition is met.
We can use jump to jump to a particular line number in the program.
hello
C:\Users\pavan\OneDrive\Documents>python -m pdb TestPgm.py > c:\users\pavan\onedrive\documents\testpgm.py(2)<module>() -> def maximum(a, b): (Pdb) jump 13 > c:\users\pavan\onedrive\documents\testpgm.py(13)<module>() -> z = maximum(a, b)
These are the commonly used commands in the debugger. If we want to terminate the debugger (which also terminates the program), we can use the q command to quit.
Command |
Function |
help |
To
display all commands |
where |
Display
the stack trace and line number of the current line |
next |
Execute
the current line and move to the next line ignoring function calls |
until |
Skips
to that line number |
c |
continue until trigger is met |
bt |
Traceback
to check how we reached that point |
jump |
Jump to
that particular line number in the program |
step |
Step
into functions called at the current line |
post-mortem debugger
Post-mortem debugging means entering into debug mode after a failure has occured while executing the program. pdb supports post-mortem debugging through the pm() and post_mortem() functions. These functions look for active trace back and start the debugger at the line in the call stack where the exception occurred
Let us say that we run the program through the command line and we want to bring up the debugger at the point of exception. We need to add this code:
1 2 3 4 5 6 | import sys import pdb def debughook(etype, value, tb): pdb.pm() # post-mortem debugger sys.excepthook = debughook |
This works by asking Python to register the debugger pdb.pm() as the exception handler when an uncaught exception is raised. When it is called, it will look for the last exception raised and start the debugger at that point.
No comments:
Post a Comment