Debugging Jupyter Notebooks Will Boost Your Productivity | by Eyal Trabelsi | Towards Data Science

We all encounter bugs in our code while developing programs, logging is a great way to debug our code and probably the most intuitive one. A normal way to do that is to add the print statement in your code which helps us track down the source of many issues.
import randomdef find_max (values):   max = 0   print(f”Initial max is {max}”)   for val in values:      if val > max:         max = val   return maxfind_max(random.sample(range(100), 10))
Easy
No installation required
Can be spammy
Hard to pinpoint error-prone locations
We saw print statements help us find relevant information regarding the issues, but these tools aren’t enough to find every root cause. When we need something more powerful, it’s time to try Python’s built-in interactive debugger.
pdb module provides an interactive debugging environment for Developers to debug Python programs (including jupyter notebooks). To initiate the debugger, all we have to do is import the pdb built-in module and run its set_trace function.
import randomdef find_max (values):   max = 0   import pdb; pdb.set_trace()   for val in values:      if val > max:         max = val   return maxfind_max(random.sample(range(100), 10))
Demo:
Dynamic.
No installation required.
Mature (More features, good documentation, and fewer bugs).
Very scary.
Steep learning curve.
Introduction to PDB
The Glory of pdb’s set trace
Some would rightfully point out that Jupyter already supports pdb and that's enough, but as developers, we tend to prefer the easy way AKA GUI.
PixieDebugger is the first visual Python debugger for Jupyter notebooks and includes a source editor, local variable inspector, console output, the ability to evaluate Python expressions in the current context, breakpoints management, and a toolbar for controlling code execution.
import contextlibwith contextlib.redirect_stdout(None):   import pixiedust# New Cell%%pixie_debuggerdef find_max (values):   max = 0   import pdb; pdb.set_trace()   for val in values:      if val > max:         max = val   return maxfind_max(random.sample(range(100), 10))
Dynamic.
Easy.
Additional installation required.
Working on Jupyter notebooks but not in Jupiter lab.
Not mature (bad documentation and evaluation of assignment fail).
pip install pixiedust
Medium Post
Very similar to pixie-dust GUI debugger made by Jupyter Lab itself, it still quite new but we can set breakpoints in notebook cells and source files, inspect variables, navigate the call stack and more.
import contextlibwith contextlib.redirect_stdout(None):   import pixiedust# New Celldef find_max (values):   max = 0   import pdb; pdb.set_trace()   for val in values:      if val > max:         max = val   return maxfind_max(random.sample(range(100), 10))
Dynamic.
Easy.
No additional code.
Additional installation required.
Require a new interpreter.
Working on Jupyter notebooks but not in Jupiter lab.
Installation is somewhat hard.
Not mature (bad documentation and evaluation of assignment fail).
For each conda environment
conda install -y -c conda-forge xeus-python=0.6.12 notebook=6 ptvsdjupyter labextension install @jupyterlab/debugger
Xeus Interpreter
Visual debugger
ipdb- PDB On steroids.
pudb- PDB With GUI.
In conclusion, there are many techniques that one can use in order to debug Jupiter Notebooks:
First people should use Logging in order to isolate problems
Power users should dedicate their time to learning pdb as you never know it will benefit you.
Lastly depending on whether you use bare notebooks or Jupyter Lab you should use pixiedust and Jupyter debugger.
I hope this post will make people more productive in the notebook environment. I hope I was able to share my enthusiasm for this fascinating topic and that you find it useful, and as always I am open to any kind of constructive feedback.