Debugging is an essential skill for any software developer. It allows us to find and fix errors in our code, improve quality and performance, and learn from our mistakes. One of the most common and powerful tools for debugging Python code is the . PDB is a module that provides an interactive command-line interface for inspecting and manipulating the state of a running program. Python Debugger (PDB) With PDB, we can set breakpoints, step through the code line by line, examine variables and expressions, modify values, and more. However, using PDB can also be cumbersome and tedious. To invoke PDB, we need to import the pdb module and insert a statement in our code where we want to pause the execution and enter the debugger. pdb.set_trace() import pdb def add(a: int, b:int) -> int: pdb.set_trace() # pause here and enter the debugger return a + b print(add(1, 2)) This means we have to modify our source code every time we want to debug it, and remember to remove or comment out the pdb statements when we are done. Moreover, if we want to use a different debugger than PDB, such as IPython or PuDB, we have to change the import statement and the function call accordingly. Fortunately, introduced a new built-in function that simplifies this process: . The function is a convenient way to start a debugger at any point in our code without having to import anything or write debugger-specific code. Python 3.7 breakpoint() breakpoint() All we have to do is insert a statement where we want to pause the execution, and enter the debugger! breakpoint() In this article, we will learn what is, how to use it with PDB and other debuggers, and how to change its behavior with environment variables. breakpoint() Using breakpoint() When using PDB, we need to learn a couple of commands to interact with the debugger. There is a long list of commands PDB gives us, but we only need to know a few of them to get started. For example, if we want to print values, we use the command. p If we want to execute the next line of code, we use the or command. To continue execution until the next breakpoint, we use the or command. Finally, the or command shows us the code around the current line we are debugging. n next c continue l list Command Description p [variable_name] Print the value of an expression. or n next Continue execution until the next line in the current function is reached or it returns. or s step Execute the current line, and stop at the first possible occasion (either in a function that is called or in the current function). or c continue Continue execution, only stop when a breakpoint is encountered. or l list List the source code for the current file. or h help Prints a list of commands we can use with PDB. Let’s see how works. Below is a recursive function that calculates the factorial of a given number. I’ve added a statement to the function, so we can pause the execution and enter the debugger. breakpoint() breakpoint() # main.py def factorial(number: int) -> int: if number < 0: raise ValueError("`n` must be non-negative.") elif number <= 1: return 1 else: breakpoint() # pause here and enter the debugger return number * factorial(number - 1) # factorial(5) is: 5 * 4 * 3 * 2 * 1 = 120 print(factorial(5)) When we run this code, the program will stop at the statement and launch the default debugger, which is PDB by default. We can then use the PDB commands to inspect and manipulate the program state. breakpoint() https://replit.com/@DylanPaulus/factorial-breakpoint?embedable=true#main.py We can see that pauses the execution at the line where it is called. By using the commands we learned above, we can inspect the program state ( to see the value of ) and step through the code line by line ( ). breakpoint() p number n s Changing the Debugger Behavior One of the advantages of using over is that we can switch to a different debugger at any time. By setting the environment variable, we can tell Python which debugger we would like to use. breakpoint() pdb.set_trace() PYTHONBREAKPOINT For example, if we want to use IPython as our debugger, we can run: $ export PYTHONBREAKPOINT=IPython.core.debugger.set_trace $ python3 main.py Another advantage of using is that we can disable all breakpoints in our code by setting the environment variable to 0. breakpoint() PYTHONBREAKPOINT This is useful when we want to run our code without entering the debugger, without having to remove or comment out all the statements. breakpoint() $ export PYTHONBREAKPOINT=0 $ python3 main.py End is a much-needed improvement over ! It gives us the ability to quickly debug our code and easily switch between different debuggers. breakpoint() pdb.set_trace()