{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Debugging\n", "\n", "IPython contains various tools to analyse faulty code, essentially the exception reporting and the debugger." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Check exceptions with `%xmode`\n", "\n", "If the execution of a Python script fails, an exception is usually thrown and relevant information about the cause of the error is written to a traceback. With the `%xmode` magic function you can control the amount of information that is displayed in IPython. Let's look at the following code for this:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "def func1(a, b):\n", " return a / b\n", "\n", "\n", "def func2(x):\n", " a = x\n", " b = x - 1\n", " return func1(a, b)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[2], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mfunc2\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n", "Cell \u001b[0;32mIn[1], line 8\u001b[0m, in \u001b[0;36mfunc2\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 6\u001b[0m a \u001b[38;5;241m=\u001b[39m x\n\u001b[1;32m 7\u001b[0m b \u001b[38;5;241m=\u001b[39m x \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc1\u001b[49m\u001b[43m(\u001b[49m\u001b[43ma\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mb\u001b[49m\u001b[43m)\u001b[49m\n", "Cell \u001b[0;32mIn[1], line 2\u001b[0m, in \u001b[0;36mfunc1\u001b[0;34m(a, b)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfunc1\u001b[39m(a, b):\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43ma\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mb\u001b[49m\n", "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "func2(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Calling `func2` leads to an error and the traceback shows exactly what happened: each line shows the context of each step that ultimately led to the error. With the `%xmode` magic function (short for exception mode) we can control which information should be displayed to us.\n", "\n", "`%xmode` takes a single argument, the mode, and there are three options:\n", "* `Plain`\n", "* `Context`\n", "* `Verbose`\n", "\n", "The default setting is `Context` and outputs something like the one above. `Plain` is more compact and provides less information:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception reporting mode: Plain\n" ] }, { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "Traceback \u001b[0;36m(most recent call last)\u001b[0m:\n", "\u001b[0m Cell \u001b[1;32mIn[3], line 2\u001b[0m\n func2(1)\u001b[0m\n", "\u001b[0m Cell \u001b[1;32mIn[1], line 8\u001b[0m in \u001b[1;35mfunc2\u001b[0m\n return func1(a, b)\u001b[0m\n", "\u001b[0;36m Cell \u001b[0;32mIn[1], line 2\u001b[0;36m in \u001b[0;35mfunc1\u001b[0;36m\n\u001b[0;31m return a / b\u001b[0;36m\n", "\u001b[0;31mZeroDivisionError\u001b[0m\u001b[0;31m:\u001b[0m division by zero\n" ] } ], "source": [ "%xmode Plain\n", "func2(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `Verbose` mode shows some additional information, including the arguments for any functions being called:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception reporting mode: Verbose\n" ] }, { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mZeroDivisionError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[4], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m get_ipython()\u001b[38;5;241m.\u001b[39mrun_line_magic(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mxmode\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mVerbose\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m----> 2\u001b[0m \u001b[43mfunc2\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n", "Cell \u001b[0;32mIn[1], line 8\u001b[0m, in \u001b[0;36mfunc2\u001b[0;34m(x=1)\u001b[0m\n\u001b[1;32m 6\u001b[0m a \u001b[38;5;241m=\u001b[39m x\n\u001b[1;32m 7\u001b[0m b \u001b[38;5;241m=\u001b[39m x \u001b[38;5;241m-\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc1\u001b[49m\u001b[43m(\u001b[49m\u001b[43ma\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mb\u001b[49m\u001b[43m)\u001b[49m\n a \u001b[0;34m= 1\u001b[0m\u001b[0;34m\n \u001b[0mb \u001b[0;34m= 0\u001b[0m\n", "Cell \u001b[0;32mIn[1], line 2\u001b[0m, in \u001b[0;36mfunc1\u001b[0;34m(a=1, b=0)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfunc1\u001b[39m(a, b):\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43ma\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m/\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mb\u001b[49m\n a \u001b[0;34m= 1\u001b[0m\u001b[0;34m\n \u001b[0mb \u001b[0;34m= 0\u001b[0m\n", "\u001b[0;31mZeroDivisionError\u001b[0m: division by zero" ] } ], "source": [ "%xmode Verbose\n", "func2(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This additional information can help narrow down the reason for the exception. Conversely, however, the `Verbose` mode can lead to extremely long tracebacks in the case of complex code, in which the essential points can hardly be recognized." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Debugging with `%debug`\n", "\n", "Debugging can help if an error cannot be found by reading a traceback. The Python standard for interactive debugging is the Python debugger `pdb`. You can use it to navigate your way through the code line by line to see what is possibly causing an error. The extended version for IPython is `ipdb`.\n", "\n", "In IPython, the `%debug`-magic command is perhaps the most convenient way to debug. If you call it after an exception has been thrown, an interactive debug prompt will automatically open during the exception. Using the `ipdb` prompt, you can examine the current status of the stack, examine the available variables and even run Python commands.\n", "\n", "Let's look at the last exception, then do some basic tasks:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> \u001b[0;32m/var/folders/hk/s8m0bblj0g10hw885gld52mc0000gn/T/ipykernel_89993/3792871231.py\u001b[0m(2)\u001b[0;36mfunc1\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m 1 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc1\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m----> 2 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 3 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 4 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 5 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> print(a)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> print(b)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> quit\n" ] } ], "source": [ "%debug" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, the interactive debugger does a lot more – we can also go up and down the stack and examine the values of variables:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "> \u001b[0;32m/var/folders/hk/s8m0bblj0g10hw885gld52mc0000gn/T/ipykernel_89993/3792871231.py\u001b[0m(2)\u001b[0;36mfunc1\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m 1 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc1\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m----> 2 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 3 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 4 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 5 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> u\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "> \u001b[0;32m/var/folders/hk/s8m0bblj0g10hw885gld52mc0000gn/T/ipykernel_89993/3792871231.py\u001b[0m(8)\u001b[0;36mfunc2\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m 4 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 5 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 6 \u001b[0;31m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 7 \u001b[0;31m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m----> 8 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc1\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> u\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "> \u001b[0;32m/var/folders/hk/s8m0bblj0g10hw885gld52mc0000gn/T/ipykernel_89993/1541833627.py\u001b[0m(2)\u001b[0;36m\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m 1 \u001b[0;31m\u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_line_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'xmode'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Verbose'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m----> 2 \u001b[0;31m\u001b[0mfunc2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> d\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "> \u001b[0;32m/var/folders/hk/s8m0bblj0g10hw885gld52mc0000gn/T/ipykernel_89993/3792871231.py\u001b[0m(8)\u001b[0;36mfunc2\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m 4 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 5 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 6 \u001b[0;31m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 7 \u001b[0;31m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m----> 8 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc1\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> print(x)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> list\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;32m 3 \u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[1;32m 4 \u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[1;32m 5 \u001b[0m\u001b[0;32mdef\u001b[0m \u001b[0mfunc2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[1;32m 6 \u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[1;32m 7 \u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m----> 8 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc1\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> q\n" ] } ], "source": [ "%debug" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This greatly simplifies the search for the function calls that led to the error.\n", "\n", "If you want the debugger to start automatically when an exception is thrown, you can use the `%pdb`-magic function to enable this behavior:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Exception reporting mode: Plain\n", "Automatic pdb calling has been turned ON\n" ] }, { "ename": "ZeroDivisionError", "evalue": "division by zero", "output_type": "error", "traceback": [ "Traceback \u001b[0;36m(most recent call last)\u001b[0m:\n", "\u001b[0m Cell \u001b[1;32mIn[7], line 3\u001b[0m\n func2(1)\u001b[0m\n", "\u001b[0m Cell \u001b[1;32mIn[1], line 8\u001b[0m in \u001b[1;35mfunc2\u001b[0m\n return func1(a, b)\u001b[0m\n", "\u001b[0;36m Cell \u001b[0;32mIn[1], line 2\u001b[0;36m in \u001b[0;35mfunc1\u001b[0;36m\n\u001b[0;31m return a / b\u001b[0;36m\n", "\u001b[0;31mZeroDivisionError\u001b[0m\u001b[0;31m:\u001b[0m division by zero\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "> \u001b[0;32m/var/folders/hk/s8m0bblj0g10hw885gld52mc0000gn/T/ipykernel_89993/3792871231.py\u001b[0m(2)\u001b[0;36mfunc1\u001b[0;34m()\u001b[0m\n", "\u001b[0;32m 1 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc1\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m----> 2 \u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0ma\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 3 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 4 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\u001b[0;32m 5 \u001b[0;31m\u001b[0;32mdef\u001b[0m \u001b[0mfunc2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0m\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> print(b)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0\n" ] }, { "name": "stdin", "output_type": "stream", "text": [ "ipdb> q\n" ] } ], "source": [ "%xmode Plain\n", "%pdb on\n", "func2(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you have a script that you want to run in interactive mode from the start, you can do so with the command `%run -d`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Essential commands of the `ipdb`\n", "\n", "| Command | Description |\n", "| -------------- | ------------------------------------------------------------------------- |\n", "| `list` | Show the current location in the file |\n", "| `h`(`elp`) | Display a list of commands or find help on a specific command |\n", "| `q`(`uit`) | Terminates the debugger and the program |\n", "| `c`(`ontinue`) | Exit the debugger, continue in the program |\n", "| `n`(`ext`) | Go to the next step in the program |\n", "| `` | Repeat the previous command |\n", "| `p`(`rint`) | Print variables |\n", "| `s`(`tep`) | Step into a subroutine |\n", "| `r`(`eturn`) | Return from a subroutine |\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Further information on the IPython debugger can be found at [ipdb](https://github.com/gotcha/ipdb)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.13 Kernel", "language": "python", "name": "python313" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.0" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 4 }