<jupyter_start><jupyter_text>Essential Debugging Commands **A quick note on syntax**: Many of the essential debug commands have a long and a short version. For instance, for help, you can use `h` or `help`. For brevity I'll denote this as `h(elp)` which I intend to mean "`h` and `help` both work"   Setup I've copied the error-causing code into the function `e()` in a file called error.py. We can now use the `%run` magic from chapter 3 to load our error-causing function into this notebook's state, so that we have something to debug without cluttering things up. Anytime you need to generate an error for debug practice, you can just call `e()` and then `%debug`.<jupyter_code>#Load all our functions
%run error.py
#this is meant to fail
e()<jupyter_output><empty_output><jupyter_text>**Note:** If you accidentally call run the debug cell in which the debugger is already running, the only way out is to restart the kernel, interrupting won't work. This is very annoying so if you know a better way, please let me know and I'll credit you here.   Meta Commands  `h(elp)` - list all debugger commands `h(elp)` lists all debugger commands  `h(elp) commandname` will give you a docstring and usage for `commandname`, e.g. `h quit`<jupyter_code>%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(25)[0;36mthird[1;34m()[0m
[1;32m     23 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m4[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     24 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 25 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     26 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     27 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> h

Documented commands (type help <topic>):
========================================
EOF    cl         disable  interact  next    psource  rv         unt   
a      clear      display  j         p       q        s          until 
alias  commands   down     jump      pdef    quit     source     u[...]<jupyter_text>`q(uit)` - quit the debugger Make sure you're comfortable using these two before we jump into the rest. Run them below if you haven't already<jupyter_code>%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(25)[0;36mthird[1;34m()[0m
[1;32m     23 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m4[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     24 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 25 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     26 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     27 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> q<jupyter_text>Commands to show values/expressions  `p(rint)` to view any variable/expression Okay, I have a confession, `p(rint)` is actually worthless, you can print any variable/expression just by typing said variable or expression. `print cube` and `cube` will both do almost the exact same thing, but I needed a header for this section. The one place you'll need `p(rint)` is if your variable has a name that is reserved in the debugger, e.g. `h` which is reserved for help.Commands to try:- `p cube`- `cube`- `cube**(1/3)`- `import this`- Literally any valid expression you can think of<jupyter_code>%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(25)[0;36mthird[1;34m()[0m
[1;32m     23 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m4[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     24 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 25 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     26 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     27 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> cube
8000
ipdb> cube**(1/3)
19.999999999999996
ipdb> import this
The Zen of Python, by <NAME>

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readabi[...]<jupyter_text>`a(rgs)` to view arguments to current function You could print them individually using what you learned above, but with `a(rgs)` you don't need to know the names and you get them all at once. Really useful if you have a lot of arguments, or if you're using `*args` or `**kwargs`<jupyter_code>%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(17)[0;36mthird[1;34m()[0m
[1;32m     15 [1;33m[1;31m#of a string causing a TypeError when we try to concatenate them[0m[1;33m[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     16 [1;33m[1;32mdef[0m [0mthird[0m[1;33m([0m[0mcube[0m[1;33m,[0m [0mmessage[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 17 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     18 [1;33m[1;33m[0m[0m
[0m[1;32m     19 [1;33m[1;31m#start the stack trace[0m[1;33m[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> a
cube = 8000
message = 'the cube of the product is'
ipdb> q<jupyter_text>Commands to print code  `l(ist)` to show the surrounding source code `l(ist)` shows the 5 lines before and 5 lines after your current position<jupyter_code>%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(23)[0;36mthird[1;34m()[0m
[1;32m     21 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m3[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     22 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 23 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     24 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m4[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     25 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> l
[0;32m     18 [0m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0;32m     19 [0m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m2[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0;32m     20 [0m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0;3[...]<jupyter_text>`ll` or `longlist` to see all the code `ll`/`longlist` will show you the current function in it's entirety<jupyter_code>%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(25)[0;36mthird[1;34m()[0m
[1;32m     23 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m4[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     24 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 25 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     26 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     27 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> ll
[0;32m     16 [0m[1;32mdef[0m [0mthird[0m[1;33m([0m[0mcube[0m[1;33m,[0m [0mmessage[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0;32m     17 [0m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m1[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[...]<jupyter_text>`w(here)` to see the full stack trace `w` will show you the normal stack trace that is printed when you have an error outside the debugger. It's called where, because it includes an arrow showing you where you are in the stack trace.It also takes an optional argument for the number of lines to show at each level of the call stack (default value is 5). For example `w 10` will print 10 lines from each level of the stack trace<jupyter_code>%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(25)[0;36mthird[1;34m()[0m
[1;32m     23 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m4[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     24 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 25 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     26 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     27 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> h

Documented commands (type help <topic>):
========================================
EOF    cl         disable  interact  next    psource  rv         unt   
a      clear      display  j         p       q        s          until 
alias  commands   down     jump      pdef    quit     source     u[...]<jupyter_text>Commands to step through the code This is the section where you really start to get debugging superpowers. So far we haven't really done anything that we couldn't do with print statements, but that's about to change. What if the problem in your code isn't in the line that causes the error, but is somewhere earlier in the code where a variable was set to an unexpected value? How can we go back there and investigate?   Understanding breakpoints If you know what a breakpoint is and how to set one, please skip ahead. Breakpoints allow us to pause the execution of our code on a certain line so that we can inspect the variables at that point in the execution. They also allow us to control exactly how we proceed after the breakpoint, giving us options like 1. Running until we hit the next breakpoint1. Running the very next line of code1. Running until we reach the next line in the current functionBreakpoints are most commonly set by selecting a line of code to pause on, e.g. line 7 in the current function, but there are more advanced options here as well, such as pausing when a certain function is called, or even when a certain condition is met e.g. when a variable gets larger than a certain value, or a list hits a certain length. This is incredibly powerful and, if mastered, gives you the ability to step through your code line by line with complete control, in a much more efficient way than going back and forth to add print statements.  `b` to set a breakpoint - c - continue  - d - down  - u - up  - unt - until   - n - next  - s - step    `u(p)` and `d(own` to move around the stack trace<jupyter_code>%debug
e()
%debug
e()
%debug<jupyter_output>> [1;32mc:\users\rob\documents\github\nbpro\tutorials\error.py[0m(25)[0;36mthird[1;34m()[0m
[1;32m     23 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m4[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;31m1[1;32m    24 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m---> 25 [1;33m    [0mprint[0m[1;33m([0m[0mmessage[0m [1;33m+[0m [0mcube[0m[1;33m)[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     26 [1;33m    [1;32mfor[0m [0mi[0m [1;32min[0m [0mrange[0m[1;33m([0m[1;36m5[0m[1;33m)[0m[1;33m:[0m[1;33m[0m[1;33m[0m[0m
[0m[1;32m     27 [1;33m        [1;32mpass[0m[1;33m[0m[1;33m[0m[0m
[0m
ipdb> h

Documented commands (type help <topic>):
========================================
EOF    cl         disable  interact  next    psource  rv         unt   
a      clear      display  j         p       q        s          until 
alias  commands   down     jump      pdef    quit     sourc[...]
{'fraction_non_alphanumeric': 0.2202842377260982, 'fraction_numerical': 0.13565891472868216, 'mean_word_length': 5.1190711462450595, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '632947', 'license': 'Apache-2.0', 'n_tokens_mistral': 6874, 'n_tokens_neox': 5566, 'n_words': 1100, 'path': 'tutorials/5.1 Essential Debugging Commands.ipynb', 'repo_name': 'rbracco/nbpro', 'size': '12388'}