{ "cells": [ { "cell_type": "markdown", "id": "9291c943", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# Debugger" ] }, { "cell_type": "markdown", "id": "b235f4c3", "metadata": { "tags": [ "remove-cell" ] }, "source": [ "CS1302 Introduction to Computer Programming\n", "___" ] }, { "cell_type": "markdown", "id": "c70c27e5", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## Why debuggers?" ] }, { "cell_type": "markdown", "id": "b42068dc", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "As a computer programmer, your goal is to write programs which solves some tasks. But sometimes computer programs behave in an unexpected way due to *Errors* or *Bugs*. For simple programs, finding errors might be easy. However, for programs consisting many lines of code, finding errors can be very hard." ] }, { "cell_type": "markdown", "id": "99dcd7ad", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "A *Debugger* allows us to pause/break the execution of a program at a line, called a *breakpoint*, we specify. This allows us to find errors more easily." ] }, { "cell_type": "markdown", "id": "518321d8", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ " In this lab, we will learn to use a visual debugger in JupyterLab." ] }, { "cell_type": "markdown", "id": "8a8ba7ea", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## Set breakpoints" ] }, { "cell_type": "markdown", "id": "2e530535", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "To use the Jupyterlab visual debugger, ensure XPython kernel is running:" ] }, { "cell_type": "markdown", "id": "7ea37fd0", "metadata": {}, "source": [ "![xpython](images/xpython.dio.svg)\n", "\n", "If you do not see XPython or a circle next to it on the top-right-hand corner, switch to the XPython kernel by clicking the name of the current kernel on the top-right-hand corner." ] }, { "cell_type": "markdown", "id": "9b032c55", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "We will use the following code as an example to set a breakpoint. First, execute the code to see the effect." ] }, { "cell_type": "code", "execution_count": 1, "id": "807acc3a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, World!" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "msg = \"Hello, World!\"\n", "print(msg)" ] }, { "cell_type": "markdown", "id": "f7c158b4", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "To enter the debug mode, turn on the switch near on top right-hand corner: \n", "\n", "![jupyterlab debugger switch](images/jupyterlab-debug.dio.svg)" ] }, { "cell_type": "markdown", "id": "790f70af", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "The debugging sidebar should slide open. You can also open/close the sidebar by clicking the bug icon on the right." ] }, { "cell_type": "markdown", "id": "6002e585", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "**Exercise** \n", "\n", "Code cells also looks different in debug mode. What is the difference?\n", "\n", "![code cell](images/codecell.dio.svg)" ] }, { "cell_type": "markdown", "id": "fa457f02", "metadata": { "deletable": false, "nbgrader": { "cell_type": "markdown", "checksum": "723be0a25c4e145cdd163aa7318f3629", "grade": true, "grade_id": "line-number", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false }, "tags": [] }, "source": [ "YOUR ANSWER HERE" ] }, { "cell_type": "markdown", "id": "7aff4682", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "To set a breakpoint, press the dot that appears as you hover to the left of line number 2. Run the cell to see what happens." ] }, { "cell_type": "code", "execution_count": 2, "id": "3d2e28ad", "metadata": { "tags": [ "remove-output" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, World!" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "msg = \"Hello, World!\"\n", "print(msg)" ] }, { "cell_type": "markdown", "id": "9ccf2c89", "metadata": {}, "source": [ "The debugger provides quite a bit of information, organized as follows:" ] }, { "cell_type": "markdown", "id": "1cc3e136", "metadata": {}, "source": [ "* **Orange line** is the line where the execution is paused. \n", "![paused](images/paused.dio.svg)" ] }, { "cell_type": "markdown", "id": "c81abc1c", "metadata": {}, "source": [ "* **Variables panel** shows the current values of different variables. \n", "![variables](images/variables.dio.svg)" ] }, { "cell_type": "markdown", "id": "7f33d6e0", "metadata": {}, "source": [ "* **Callstack panel** provides a more detailed context of where the execution is paused. It also provides the flow control buttons to resume/stop the execution. \n", "![callstack](images/callstack.dio.svg)" ] }, { "cell_type": "markdown", "id": "cadffc2b", "metadata": {}, "source": [ "* **Breakpoints panel** shows all the breakpoints of the current debug session. \n", "![breakpoints](images/breakpoints.dio.svg)" ] }, { "cell_type": "markdown", "id": "4a441232", "metadata": {}, "source": [ "* **Source panel** highlights the source of the breakpoint at which the execution is currently paused. \n", "![source](images/source.dio.svg)" ] }, { "cell_type": "markdown", "id": "13ada4ec", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** Explain whether line 1 and 2 are executed. Use the information from the debugger to support your answer." ] }, { "cell_type": "markdown", "id": "388b3570", "metadata": { "deletable": false, "nbgrader": { "cell_type": "markdown", "checksum": "060b14b2b8a2628bca885fc8273395c3", "grade": true, "grade_id": "executed", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "source": [ "YOUR ANSWER HERE" ] }, { "cell_type": "markdown", "id": "1a85e362", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Resume execution" ] }, { "cell_type": "markdown", "id": "72bed07f", "metadata": {}, "source": [ "To resume/terminate the execution, use the following flow control buttons at the top of the callstack panel: \n", "![callstack](images/flowcontrol.dio.svg)\n", "- **Continue** button continues the execution and pause again if it hits a breakpoint.\n", "- **Terminate** button stops the execution.\n", "- **Next/Step-over** button continues the execution of program to the next statement without entering function." ] }, { "cell_type": "markdown", "id": "abbc588a", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "**Exercise** \n", "\n", "What does the following function `f(n)` computes? Try to set a breakpoint and use the flow control to understand how the program works." ] }, { "cell_type": "code", "execution_count": 3, "id": "8fc547f0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def f(n): # definition of a function\n", " return n * f(n - 1) if n > 0 else 1\n", "\n", "\n", "f(3)" ] }, { "cell_type": "markdown", "id": "6bf5c240", "metadata": {}, "source": [ "````{hint}\n", "\n", "Set the breakpoint one at a time but at different locations. If you set your breakpoint at line 5, you should use the **Step In** button to step into the execution of the function.\n", "\n", "````" ] }, { "cell_type": "markdown", "id": "10af3170", "metadata": { "deletable": false, "nbgrader": { "cell_type": "markdown", "checksum": "4977f55aff95e93021c125fe6ec165b6", "grade": true, "grade_id": "factorial", "locked": false, "points": 1, "schema_version": 3, "solution": true, "task": false } }, "source": [ "YOUR ANSWER HERE" ] }, { "cell_type": "markdown", "id": "04741656", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Run temporary code" ] }, { "cell_type": "markdown", "id": "24d25fd9", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "Sometimes, we want to run temporary code without modifying the current notebook. To do so:" ] }, { "cell_type": "markdown", "id": "104c68aa", "metadata": { "slideshow": { "slide_type": "-" } }, "source": [ "- Right click anywhere on a notebook and choose `New Console for Notebook`:\n", "\n", "![new console](images/newconsole.dio.svg)" ] }, { "cell_type": "markdown", "id": "1dee516b", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "- Type some code such as `msg` into the console input and run it with `Shift-Enter`:\n", "\n", "![console](images/console.dio.svg)" ] }, { "cell_type": "markdown", "id": "f03e435d", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "````{tip}\n", "\n", "- You can run `f(n)` for different values of `n` in the console to understand how the function works. \n", "- You can set a breakpoint in line 2 of the previous code cell containing `def f(n): ...` and run `f(3)` in the console to pause at the breakpoint. The source code containing the breakpoint will also be shown in the **Source panel**. \n", "- You can also set a breakpoint in the console input, say `f(3)`, and then step into it.\n", "- While the execution is paused, you can enter a new line of code such as `print(msg)` below `f(3)` in the console and then continue the execution to run the new line of code.\n", "\n", "````" ] }, { "cell_type": "markdown", "id": "f7493435", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "## VS Code interface (Optional)" ] }, { "cell_type": "markdown", "id": "cce34fd3", "metadata": {}, "source": [ "There are other debuggers in different interfaces. A powerful GUI debugger is available in the vscode interface: \n", "- `File`$\\to$ `New Launcher`$\\to$ `VS Code`" ] }, { "cell_type": "markdown", "id": "fad986af", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "Follow the [official guide](https://code.visualstudio.com/docs/datascience/jupyter-notebooks) to install the python/jupyter extension and debug a jupyter notebook." ] } ], "metadata": { "jupytext": { "text_representation": { "extension": ".md", "format_name": "myst", "format_version": 0.13, "jupytext_version": "1.10.3" } }, "kernelspec": { "display_name": "Python 3.8 (XPython)", "language": "python", "name": "xpython" }, "language_info": { "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "version": "3.8.10" }, "source_map": [ 14, 18, 23, 27, 31, 35, 39, 43, 47, 53, 57, 62, 68, 72, 80, 84, 88, 93, 97, 102, 107, 112, 117, 122, 126, 130, 134, 142, 148, 154, 162, 166, 170, 174, 180, 186, 197, 201, 206 ] }, "nbformat": 4, "nbformat_minor": 5 }