Debugging and Prototyping
The Problem
When you code, you have problems. It’s inevitable. Let’s call them bugs. You need to find them and fix them. But how?
Then you want to create something on the side, and see if it works.
The Solution
There’s no one-size-fits-all solution, no silver bullet. We can only play around with some slingshots and see what works best for us.
Debugging
It’s a crucial part of the development process. If you start with tests, you may need to debug less, but it’s still important to have tools that make it easier.
IDE debugger
Debugger is a tool that allows you to pause the execution of the code, inspect variables, and step through the code. Modern IDEs like VS Code and PyCharm come with built-in debuggers that make it easy to identify and fix issues. You can set breakpoints, step through the code, and see the values of variables at each step. You can even modify the variables on the fly! Without writing here more, we suggest you check the documentation of your IDE. VSCode, PyCharm.
Modern IDEs have built-in debuggers that work great with Python, allow you to set breakpoints, inspect variables, modify them, run arbitrary code in a breakpoint, and more.
Debugging with IDE should be your first choice when you have a problem.
print
Icecream debugging
print
Sometimes, you just can’t resist and you need to print
something.
- First, consider using the IDE debugger.
- Second, try to use logging instead of
print
. - Finally, if you really need to use
print
, consider usingicecream
instead…
You’ve probably used print
many times, but it’s not the best tool for debugging. We recommend using icecream
instead. It’s a modern, colorful, and more informative version of print
, instead of writing print("variable:", variable)
, you can write ic(variable)
and it will print the variable name and its value, and the line where it was called. icecream
knows how to format different types of data, so you don’t have to worry about it.
You can use it with:
from icecream import ic
= [1, 2, 3]
l ic(variable)
Use icecream
instead of print
for better debugging experience.
Read more about icecream
in the official repository.
Quick prototyping
You often debug while writing new features. Let’s call it quick prototyping.
Test Driven Development (TDD)
First, we recommend writing tests for the things you want to implement. This might sound counterintuitive, as you don’t have anything to test yet, but it’s a good practice, it’s called TDD (Test-Driven Development). You write a test that fails, then you write the code that makes the test pass. By making starting with the test, you know what you want to achieve, and you can focus on that. Additionally, it helps you not to entangle the code too much. And well, you have the tests!
Start developing new features with writing tests for them!
The interactive prototyping
The R community is familiar with running code in the console and seeing the results immediately. This is very powerful and allows for quick prototyping. Modern IDEs like VS Code also allows this in python. Just select a piece of code, hit Shift+Enter
and see the results in the interactive console.
However, the results are quickly lost and hard to reproduce. We propose using jupyter notebooks for this purpose, as presented in the notebooks/01_experiment.ipynb
file. You can run the code cell by cell, see the results, and add comments, you can easily attach the debugger to the running code.
There are many workflows for using notebooks for prototyping. The one we suggest is to actually write classes, functions directly in the main codebase and import it to the notebook for experimenting. The hot realoading in notebooks with autoreload
magic command helps here a lot - it reloads the imported modules every time you run the cell, so you don’t have to restart the kernel every time you make a change in the code!
Just so you know, you can also easily export the notebook to a python script. However, we recommend operating on the codebase directly, as it’s easier to maintain and test.