@extends('template')
@section('title')
Lab 8: Part 1. Tracing & Debugging Loops
@stop
@section('content')
# Lab 8: Part 1. Tracing & Debugging Loops
**Tracing** refers to keeping track of the values used by a program as it runs. This can be achieved through printing, by using the debugger, or even using a pencil and paper or just your imagination. Writing an iteration table is a kind of tracing.
**Debugging** refers to finding and fixing errors to make something work correctly.
**Testing** (which we'll delve into in the following section) refers to setting up examples and establishing expectations so that we can see if something really works or not. Again it can be done by hand, or by using a program or library.
## Tracing with `print`
The most straightforward way to trace code is to add `print` function
calls to the code itself, so that as it runs, it prints out the
information you need to know. This takes a bit of work, but it always
saves time compared to simply guessing what the problem might be and
trying different things.
Partner A
In **the provided starter file `tracing.py`**, there is a copy of the
`hasCGBlock` function from the genetics problem set task (there are also
several broken copies numbered `hasCGBlock1` through `hasCGBlock3`). Your
job is to add `print` calls so that it prints out the trace information
shown in these examples (note that the provided version works correctly):
```txt
>>> hasCGBlock('CGAU')
base C True
run 1
base G True
run 2
base A False
run 0
base U False
run 0
no blocks
False
```
```txt
>>> hasCGBlock('CGCAGGGCCUAGC')
base C True
run 1
base G True
run 2
base C True
run 3
base A False
run 0
base G True
run 1
base G True
run 2
base G True
run 3
base C True
run 4
base C True
found it
True
```
## Debugger limitations
Next, we'll use Thonny's built-in debugger to trace our code, which
requires less setup than using `print`s, and can tell us more information
at once. Recall that [we introduced the debugger back in lab
2](/labs/lab02/debugger). If you don't remember how it works, briefly
review the "Using the debugger" section of that lab which explains how
the different buttons work. The main ones we will use are the "start
debugging" button, the "step into" button, and the "resume" button.
Before we get started, we also need to be aware of two important
limitations:
1. The debugger will only run code in your file, not code that you put
into the shell. So your file itself must call the function that you
want to debug.
2. The debugger slows things down, even when a breakpoint is set up,
because it has to record every step of your program. Sometimes, when
we provide very large data files, trying to import these will take
forever in the debugger. In cases like this, it's best to temporarily
comment out any imports for very large Python files while using the
debugger, if you can. If that's not possible, you may have to rely on
simpler methods like `print`s to trace your code.
## Tracing with the debugger
The debugger can be set up to pause at certain points in the code,
instead of running step by step. These are called "breakpoints." To set a
breakpoint, double-click on the margin of Thonny where the line numbers
are written, and a red dot should appear next to the line number you
double-clicked on, which will look like this:
![A screenshot of part of the Thonny window showing the first few lines of the hasCGBlock definition from the provided tracing.py file. A breakpoint has been set on line 20, which is the if statement on the first line of the for loop.](breakpoint.png)
When any breakpoints are set, running the debugger will fast-forward
until it reaches a line with a breakpoint on it (and it will run to
completion if it never reaches such a line). It will pause at that point,
and you can use the normal stepping buttons to keep running step-by-step,
or you can also use the resume button to continue until the next
breakpoint is hit.
By setting a breakpoint on the very first line inside of a for loop, we
can use the resume button to step through each iteration of the loop. And
in the function call frame window that pops up, the local variables of
the function will be displayed, so we can watch the values update on each
iteration, as shown in this picture:
![A screenshot of Thonny showing the debugger paused on the first line of the loop in hasCGBlock, and indicating the function call frame window that's open, the yellow box in Thonny highlighting the if/else block which is about to execute, and the local variables pane at the bottom showing the value of each local variable, including base ('C'), run (0), and sequence ('CGAGGGCCUC').](debugger_open.png)
Take a moment to step through the `hasCGBlock` loop and watch the values
update so you're familiar with how to use the debugger before moving on
to the next part of this lab. Remember to add a function call to the file
so that it will actually run when you start it in debug mode.
@include('/labs/lab08/_toc')
@stop