if not input('Load JupyterAI? [Y/n]').lower()=='n':
%reload_ext jupyter_ai
Motivation¶
Computer programs can sometimes behave in an unexpected way due to errors or bugs. Finding the errors might be easy for simple programs. However, for programs consisting of many lines of code, finding errors can be very hard.
A debugger allows us to pause the execution of a program at a line of code set as a breakpoint. This allows us to find errors more easily. In this lab, we will learn to use the visual debugger in JupyterLab.
Debugging in JupyterLab¶
To enter the debug mode, click on the debugger icon 🕷️ in the toolbar. The debugging sidebar should slide open. You can also open/close the sidebar by clicking the debugger icon on the right side bar.
We will use the following code as an example to set a breakpoint. First, execute the code to see the effect.
msg = "Hello, World!"
print(msg)
Code cells look different in debug mode: Each line of the code cell has a line number on the left margin. To set a breakpoint:
- Press the dot that appears as you hover to the left of line number 2.
- Run the cell and observe that only line 1 is executed but not line 2.
Sometimes, it is helpful to run temporary code that shares the same context as the notebook, but without modifying the notebook. Normally, this can be done using a console:
- Right click anywhere on a notebook and choose
New Console for Notebook
: - Type some code such as
msg
into the console input and run it withShift-Enter
:
However, if you need to run temporary code while debugging a code cell, the console above won’t work because a breakpoint also pauses the execution of the console. We need a special console called the debug console:
Set a breakpoint at Line 2 of the above code and run it in debug mode.
- Click the
icon in the callstack panel to open a debug console. Enter the code
print(msg)
and clickEvaluate
. Explain what gets printed to the cell output. - Repeat the last step but evaluate the code
msg="Message modified!"
in the debug console instead. Observe the value ofmsg
from the Variables panel.
Finally, to resume/terminate the execution, use the following flow control buttons at the top of the callstack panel:
- Next/Step-over button continues the execution of program to the next line of code to be executed.
- Continue button continues the execution and pause again if it hits a breakpoint.
- Terminate button stops the execution.
def kua(a, k):
if k > 1:
return kua(a, k-1) ** a
return a
def kua(a, k):
# YOUR CODE HERE
raise NotImplementedError
# tests
assert kua(2, 0) == 1
assert kua(2, 1) == 2
assert kua(2, 2) == 2**2
assert kua(2, 3) == 2**2**2
assert kua(2, 4) == 2**2**2**2
assert kua(3, 0) == 1
assert kua(3, 1) == 3
assert kua(3, 2) == 3**3
assert kua(3, 3) == 3**3**3
Other Debuggers¶
Seeing is believing. You can also debug your code by visualizing the code execution.
First, load the divewidgets
using a line magic:
%reload_ext divewidgets
Then, create a cell magic with the Python code you want to visualize:
%%optlite --height 500
def kua(a, k):
if k > 1:
return kua(a, k-1) ** a
return a
assert kua(2, 4) == 2**2**2**2
Try the following:
- Drag the slider to time-travel the code execution.
- Click any lines with code to toggle breakpoints, and click
Next >
(< Prev
) to go the the next (previous) breakpoint. - Click the
Edit the code
link to edit the code. - Click the
Permalink
button to generate a url of the code, and copy and paste the url to a new browser window to run the visualization there. - Click the
Live Edit
button to live edit the code in a new browser window, where your changes to the code are immediately visualized. You can also time-travel and generate a permalink there.
Run the following cell to see additional options available to the cell magic.
%%optlite?
If you’re struggling to understand or debug a piece of code, you can use OPTLite to share a link of the code with others. You can create a permalink like this:
If you change mode=edit
in the query string to mode=display
, the visualization will start automatically:
To automatically enter live editing mode, specify live.html
in the path:
OPTLite is a serverless setup that allows you to run the popular learning tool, Online Python Tutor, locally on your browser without any advertisements or restrictions on your code. We developed OPTLite to enable offline use once the page is loaded.
VSCode offers a more powerful debugging that allows programmers to debug both jupyter notebooks or python scripts with conditional breakpoints:
To practice debugging with VSCode, try to understand why the function is_perfect_square
from untils.py
fails on the obvious perfect square . If you are not afraid of challenges, try to fix the code with as few modifications as possible.
from importlib import reload
import utils
reload(utils) # to reload updates to utils.py without restarting kernel
utils.is_perfect_square((10**23) ** 2)
Glossary¶
- breakpoint
- A designated point in a program’s code where execution will pause, allowing the programmer to examine the program’s state and behavior at that point. Breakpoints are often used in conjunction with a debugger to help identify and resolve errors or bugs in a program.
- bug
- An error or defect in a software program that causes it to behave unexpectedly or not according to its intended purpose. Bugs can range from minor issues to major problems that can cause crashes or data loss.
- callstack
- A data structure that keeps track of the functions or procedures that have been called in a program, along with their parameters and return values. The callstack is used by the program to keep track of where it is in the execution process and to manage memory usage.
- console
- A command-line interface or text-based window used for interacting with a program or operating system. The console allows users to enter commands and view output from the system or program.
- debugger
- A tool or program used to identify and resolve errors or bugs in software code. Debuggers can be used to step through code, examine variables and data structures, and identify the source of errors in a program.
- flow control
- The process of controlling the order in which a program executes its instructions. Flow control can be achieved through conditional statements, loops, and other control structures that allow the program to make decisions and repeat actions based on certain conditions.
The path should be in lower case even though the debugger shows it in upper case.