Final Up to date on January 22, 2022
There are alternative ways of debugging code in Python, certainly one of which is to introduce breakpoints into the code at factors the place one wish to invoke a Python debugger. The statements that one would use to enter a debugging session at totally different name websites, rely on the model of the Python interpreter that one is working with, as we will be seeing on this tutorial.Â
On this tutorial, you’ll uncover varied methods of setting breakpoints in numerous variations of Python.Â
After finishing this tutorial, you’ll know:
- invoke the
pdb
debugger in earlier variations of Python. - make use of the brand new, built-in
breakpoint() perform launched in Python 3.7. - write your personal
breakpoint() perform to simplify the debugging course of in earlier variations of Python. - use a autopsy debugger
Let’s get began.Â

Setting Breakpoints in Completely different Variations of Python
Picture by Josh Withers, some rights reserved.
Tutorial overview
This tutorial is split into three elements; they’re:
- Setting Breakpoints in Python Code
- Invoking the pdb Debugger in Earlier Variations of Python
- Utilizing the
breakpoint()
Operate in Python 3.7
- Writing One’s Personal
breakpoint()
Operate for Earlier Variations of Python - Limitations of the
breakpoint()
perform
Setting breakpoints in Python code
We have now beforehand seen that a technique of debugging a Python script is to run it within the command line with the Python debugger.Â
So as to take action, we would want to make use of of the
–m pdb command that hundreds the pdb module earlier than executing the Python script. In the identical command line interface, we’d then comply with this by a selected debugger command of alternative, comparable to
n to maneuver to the subsequent line, or
s if our intention is to step right into a perform.Â
This methodology may turn into rapidly cumbersome because the size of the code will increase. One solution to deal with this drawback and achieve higher management over the place to interrupt your code, is to insert a breakpoint straight into the code.Â
Invoking the pdb debugger in earlier variations of Python
Doing so previous to Python 3.7 would require you to
import pdb, and to name
pdb.set_trace()Â on the level in your code the place you wish to enter an interactive debugging session.Â
If we rethink, for instance, the code for implementing the final consideration mechanism, we will break into the code as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
from numpy import array from numpy import random from numpy import dot from scipy.particular import softmax  # importing the Python debugger module import pdb  # encoder representations of 4 totally different phrases word_1 = array([1, 0, 0]) word_2 = array([0, 1, 0]) word_3 = array([1, 1, 0]) word_4 = array([0, 0, 1])  # stacking the phrase embeddings right into a single array phrases = array([word_1, word_2, word_3, word_4])  # producing the load matrices random.seed(42) W_Q = random.randint(3, measurement=(3, 3)) W_K = random.randint(3, measurement=(3, 3)) W_V = random.randint(3, measurement=(3, 3))  # producing the queries, keys and values Q = dot(phrases, W_Q) Okay = dot(phrases, W_K) V = dot(phrases, W_V)  # inserting a breakpoint pdb.set_trace()  # scoring the question vectors in opposition to all key vectors scores = dot(Q, Okay.transpose())  # computing the weights by a softmax operation weights = softmax(scores / Okay.form[1] ** 0.5, axis=1)  # computing the eye by a weighted sum of the worth vectors consideration = dot(weights, V)  print(consideration) |
Executing the script now opens up the pdb
debugger proper earlier than we compute the variable scores
, and we will proceed to subject any debugger instructions of alternative, comparable to
n to maneuver to the subsequent line, or
c to proceed execution:
/Customers/multilevel marketing/most important.py(33)<module>() -> scores = dot(Q, Okay.transpose()) (Pdb) n > /Customers/multilevel marketing/most important.py(36)<module>() -> weights = softmax(scores / Okay.form[1] ** 0.5, axis=1) (Pdb) c [[0.98522025 1.74174051 0.75652026] [0.90965265 1.40965265 0.5Â Â Â Â Â Â ] [0.99851226 1.75849334 0.75998108] [0.99560386 1.90407309 0.90846923]] |
Though purposeful, this isn’t essentially the most elegant and intuitive method of inserting a breakpoint into your code. Python 3.7 implements a extra easy manner of doing so, as we will see subsequent.
Utilizing the breakpoint() perform in Python 3.7Â
Python 3.7 comes with a built-in
breakpoint()Â perform that enters the Python debugger on the name website (or the purpose within the code at which the
breakpoint()Â assertion is positioned).Â
When referred to as, the default implementation of the
breakpoint() perform will name
sys.breakpointhook(), which in flip calls the
pdb.set_trace()Â perform. That is handy as a result of we is not going to must
import pdb and name
pdb.set_trace()Â explicitly ourselves.Â
Let’s rethink the code for implementing the final consideration mechanism, and now introduce a breakpoint by way of the
breakpoint() assertion:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
from numpy import array from numpy import random from scipy.particular import softmax  # encoder representations of 4 totally different phrases word_1 = array([1, 0, 0]) word_2 = array([0, 1, 0]) word_3 = array([1, 1, 0]) word_4 = array([0, 0, 1])  # stacking the phrase embeddings right into a single array phrases = array([word_1, word_2, word_3, word_4])  # producing the load matrices random.seed(42) W_Q = random.randint(3, measurement=(3, 3)) W_K = random.randint(3, measurement=(3, 3)) W_V = random.randint(3, measurement=(3, 3))  # producing the queries, keys and values Q = phrases @ W_Q Okay = phrases @ W_Okay V = phrases @ W_V  # inserting a breakpoint breakpoint()  # scoring the question vectors in opposition to all key vectors scores = Q @ Okay.transpose()  # computing the weights by a softmax operation weights = softmax(scores / Okay.form[1] ** 0.5, axis=1)  # computing the eye by a weighted sum of the worth vectors consideration = weights @ V  print(consideration) |
One benefit of utilizing the
breakpoint() perform is that, in calling the default implementation of
sys.breakpointhook() the worth of a brand new surroundings variable,
PYTHONBREAKPOINT, is consulted. This surroundings variable can take varied values, primarily based on which totally different operations could be carried out.Â
For instance, setting the worth of
PYTHONBREAKPOINT to 0 disables all breakpoints. Therefore, your code may include as many breakpoints as crucial, however these could be simply stopped from halting the execution of the code with out having to take away them bodily. If (for instance) the identify of the script containing the code is most important.py, we’d disable all breakpoints by calling it within the command line interface as follows:
PYTHONBREAKPOINT=0 python most important.py |
In any other case, we will obtain the identical final result by setting the surroundings variable within the code itself:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
from numpy import array from numpy import random from scipy.particular import softmax  # setting the worth of the PYTHONBREAKPOINT surroundings variable import os os.environ[‘PYTHONBREAKPOINT’] = ‘0’  # encoder representations of 4 totally different phrases word_1 = array([1, 0, 0]) word_2 = array([0, 1, 0]) word_3 = array([1, 1, 0]) word_4 = array([0, 0, 1])  # stacking the phrase embeddings right into a single array phrases = array([word_1, word_2, word_3, word_4])  # producing the load matrices random.seed(42) W_Q = random.randint(3, measurement=(3, 3)) W_K = random.randint(3, measurement=(3, 3)) W_V = random.randint(3, measurement=(3, 3))  # producing the queries, keys and values Q = phrases @ W_Q Okay = phrases @ W_Okay V = phrases @ W_V  # inserting a breakpoint breakpoint()  # scoring the question vectors in opposition to all key vectors scores = Q @ Okay.transpose()  # computing the weights by a softmax operation weights = softmax(scores / Okay.form[1] ** 0.5, axis=1)  # computing the eye by a weighted sum of the worth vectors consideration = weights @ V  print(consideration) |
The worth of
PYTHONBREAKPOINT is consulted each time that
sys.breakpointhook() is known as. Which means the worth of this surroundings variable could be modified through the code execution and the
breakpoint() perform would reply accordingly. Â
The
PYTHONBREAKPOINT surroundings variable may also be set to different values, comparable to to the identify of a callable. Say, as an example, that we’d like to make use of a distinct Python debugger aside from pdb, comparable to ipdb (run
pip set up ipdb first, if the debugger has not but been put in). On this case, we’d name the most important.py script within the command line interface, and hook the debugger with out making any modifications to the code itself:
PYTHONBREAKPOINT=ipdb.set_trace python most important.py |
In doing so, the
breakpoint() perform enters the ipdb debugger on the subsequent name website:
> /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy37/most important.py(33)<module>() Â Â Â Â 32 # scoring the question vectors in opposition to all key vectors —> 33 scores = Q @ Okay.transpose() Â Â Â Â 34 Â ipdb> n > /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy37/most important.py(36)<module>() Â Â Â Â 35 # computing the weights by a softmax operation —> 36 weights = softmax(scores / Okay.form[1] ** 0.5, axis=1) Â Â Â Â 37 Â ipdb> c [[0.98522025 1.74174051 0.75652026] [0.90965265 1.40965265 0.5Â Â Â Â Â Â ] [0.99851226 1.75849334 0.75998108] [0.99560386 1.90407309 0.90846923]] |
The perform can even take enter arguments as,
breakpoint(*args, **kws), that are then handed on to
sys.breakpointhook(). It’s because any callable (comparable to a 3rd celebration debugger module) would possibly settle for elective arguments, which could be handed by means of the
breakpoint() perform.Â
Writing your personal breakpoint() perform in earlier variations of Python
Let’s return to the truth that variations of Python sooner than v3.7 don’t include the
breakpoint() perform readily inbuilt. We will write our personal.Â
Equally to how the
breakpoint() perform is applied from Python 3.7 onwards, we will implement a perform that checks the worth of an surroundings variable and:
- Skips all breakpoints within the code if the worth of the surroundings variable is ready to 0.
- Enters into the default Python pdb debugger if the surroundings variable is an empty string.
- Enters into one other debugger as specified by the worth of the surroundings variable.Â
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
...  # defining our breakpoint() perform def breakpoint(*args, **kwargs):     import importlib     # studying the worth of the surroundings variable     val = os.environ.get(‘PYTHONBREAKPOINT’)     # if the worth has been set to 0, skip all breakpoints     if val == ‘0’:         return None     # else if the worth is an empty string, invoke the default pdb debugger     elif len(val) == 0:         hook_name = ‘pdb.set_trace’     # else, assign the worth of the surroundings variable     else:         hook_name = val     # cut up the string into the module identify and the perform identify     mod, dot, func = hook_name.rpartition(‘.’)     # get the perform from the module     module = importlib.import_module(mod)     hook = getattr(module, func)      return hook(*args, **kwargs)  ... |
We will embody this perform into the code and run it (utilizing a Python 2.7 interpreter, on this case). If we set the worth of the surroundings variable to an empty string, we discover that the pdb debugger stops on the level within the code at which we now have positioned our
breakpoint() perform. We will then subject debugger instructions into the command line from there onwards:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
from numpy import array from numpy import random from numpy import dot from scipy.particular import softmax  # setting the worth of the surroundings variable import os os.environ[‘PYTHONBREAKPOINT’] = ”   # defining our breakpoint() perform def breakpoint(*args, **kwargs):     import importlib     # studying the worth of the surroundings variable     val = os.environ.get(‘PYTHONBREAKPOINT’)     # if the worth has been set to 0, skip all breakpoints     if val == ‘0’:         return None     # else if the worth is an empty string, invoke the default pdb debugger     elif len(val) == 0:         hook_name = ‘pdb.set_trace’     # else, assign the worth of the surroundings variable     else:         hook_name = val     # cut up the string into the module identify and the perform identify     mod, dot, func = hook_name.rpartition(‘.’)     # get the perform from the module     module = importlib.import_module(mod)     hook = getattr(module, func)      return hook(*args, **kwargs)   # encoder representations of 4 totally different phrases word_1 = array([1, 0, 0]) word_2 = array([0, 1, 0]) word_3 = array([1, 1, 0]) word_4 = array([0, 0, 1])  # stacking the phrase embeddings right into a single array phrases = array([word_1, word_2, word_3, word_4])  # producing the load matrices random.seed(42) W_Q = random.randint(3, measurement=(3, 3)) W_K = random.randint(3, measurement=(3, 3)) W_V = random.randint(3, measurement=(3, 3))  # producing the queries, keys and values Q = dot(phrases, W_Q) Okay = dot(phrases, W_K) V = dot(phrases, W_V)  # inserting a breakpoint breakpoint()  # scoring the question vectors in opposition to all key vectors scores = dot(Q, Okay.transpose())  # computing the weights by a softmax operation weights = softmax(scores / Okay.form[1] ** 0.5, axis=1)  # computing the eye by a weighted sum of the worth vectors consideration = dot(weights, V)  print(consideration) |
> /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy27/most important.py(32)breakpoint()->None -> return hook(*args, **kwargs) (Pdb) n > /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy27/most important.py(59)<module>() -> scores = dot(Q, Okay.transpose()) (Pdb) n > /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy27/most important.py(62)<module>() -> weights = softmax(scores / Okay.form[1] ** 0.5, axis=1) (Pdb) c [[0.98522025 1.74174051 0.75652026] [0.90965265 1.40965265 0.5Â Â Â Â Â Â ] [0.99851226 1.75849334 0.75998108] [0.99560386 1.90407309 0.90846923]] |
Equally, if we set the surroundings variable to:
os.environ[‘PYTHONBREAKPOINT’] = ‘ipdb.set_trace’ |
The
breakpoint() perform that we now have applied now enters the ipdb debugger and stops on the name website:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
> /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy27/most important.py(31)breakpoint() Â Â Â Â 30 —> 31Â Â Â Â return hook(*args, **kwargs) Â Â Â Â 32 Â ipdb> n > /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy27/most important.py(58)<module>() Â Â Â Â 57 # scoring the question vectors in opposition to all key vectors —> 58 scores = dot(Q, Okay.transpose()) Â Â Â Â 59 Â ipdb> n > /Customers/Stefania/Paperwork/PycharmProjects/BreakpointPy27/most important.py(61)<module>() Â Â Â Â 60 # computing the weights by a softmax operation —> 61 weights = softmax(scores / Okay.form[1] ** 0.5, axis=1) Â Â Â Â 62 Â ipdb> c [[0.98522025 1.74174051 0.75652026] [0.90965265 1.40965265 0.5Â Â Â Â Â Â ] [0.99851226 1.75849334 0.75998108] [0.99560386 1.90407309 0.90846923]] |
Setting the surroundings variable to 0, merely skips all breakpoints and the computed consideration output is returned within the command line, as anticipated:
os.environ[‘PYTHONBREAKPOINT’] = ‘0’ |
[[0.98522025 1.74174051 0.75652026] [0.90965265 1.40965265 0.5Â Â Â Â Â Â ] [0.99851226 1.75849334 0.75998108] [0.99560386 1.90407309 0.90846923]] |
This facilitates the method of breaking into the code for Python variations sooner than v3.7, as a result of it now turns into a matter of setting the worth of an surroundings variable, quite than having to manually introduce (or take away) the
import pdb; pdb.set_trace()Â assertion at totally different name websites within the code.Â
Limitations of the breakpoint()
perform
The breakpoint()
perform means that you can convey within the debugger at some stage in this system. You might want to discover the precise place that you simply want the debugger to place the breakpoint into it. When you think about the next code:
strive: Â Â Â Â func() besides: Â Â Â Â breakpoint() Â Â Â Â print(“exception!”) |
this can convey you the debugger when the perform func()
raised exceptions. It may possibly triggered by the perform itself, or deep inside another capabilities that it calls. However the debugger will begin on the line print("exception!")
above. Which might not be very helpful.
The best way that we will convey up the debugger on the level of exception is known as the autopsy debugger. It really works by asking Python to register the debugger pdb.pm()
because the exception handler when uncaught exception is raised. When it’s referred to as, it’ll search for the final exception raised and begin the debugger at that time. To make use of the autopsy debugger, we simply want so as to add the next code earlier than this system is run:
import sys import pdb  def debughook(etype, worth, tb):     pdb.pm() # autopsy debugger sys.excepthook = debughook |
That is useful as a result of nothing else have to be modified in this system. For instance, assume we need to consider the common of $1/x$ utilizing the next program. It’s fairly straightforward to miss some nook instances however we will catch the problem when an exception is raised:
import sys import pdb import random  def debughook(etype, worth, tb):     pdb.pm() # autopsy debugger sys.excepthook = debughook  # Experimentally discover the common of 1/x the place x is a random integer in 0 to 9999 N = 1000 randomsum = 0 for i in vary(N):     x = random.randint(0,10000)     randomsum += 1/x  print(“Common is”, randomsum/N) |
after we run the above program, this system might terminate or it might increase a division by zero exception, is dependent upon whether or not the random quantity generator ever produces zero within the loop. In that case, we might even see the next:
> /Customers/multilevel marketing/py_pmhook.py(17)<module>() -> randomsum += 1/x (Pdb) p i 16 (Pdb) p x 0 |
which we discovered the exception is raised at which line and we will test the worth of the variables as we will often do in pdb
.
In actual fact, it’s extra handy to print the traceback and the exception when the autopsy debugger is launched:
import sys import pdb import traceback  def debughook(etype, worth, tb):     traceback.print_exception(etype, worth, tb)     print() # make a brand new line earlier than launching autopsy     pdb.pm() # autopsy debugger sys.excepthook = debughook |
and the debugger session will probably be began as follows:
Traceback (most current name final):   File “/Customers/multilevel marketing/py_pmhook.py”, line 17, in <module>     randomsum += 1/x ZeroDivisionError: division by zero  > /Customers/multilevel marketing/py_pmhook.py(17)<module>() -> randomsum += 1/x (Pdb) |
Additional Studying
This part gives extra assets on the subject in case you are seeking to go deeper.
Web sites
Abstract
On this tutorial, you found varied methods of setting breakpoints in numerous variations of Python.Â
Particularly, you realized:
- invoke the pdb debugger in earlier variations of Python.Â
- make use of the brand new, built-in
breakpoint() perform launched in Python 3.7. - write your personal
breakpoint() perform to simplify the debugging course of in earlier variations of Python.
Do you have got any questions?
Ask your questions within the feedback beneath and I’ll do my greatest to reply.