Skip to content

Commit d91e7a1

Browse files
committed
Add a debugging exercise
1 parent 9895d3c commit d91e7a1

File tree

2 files changed

+64
-14
lines changed

2 files changed

+64
-14
lines changed

07-debugging-post-mortem.html

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<h2 class="subtitle">Post-mortem debugging</h2>
3131
<section class="objectives panel panel-warning">
3232
<div class="panel-heading">
33-
<h2><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2>
33+
<h2 id="learning-objectives"><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2>
3434
</div>
3535
<div class="panel-body">
3636
<ul>
@@ -61,7 +61,7 @@ <h2><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2
6161
<span class="kw">return</span> -<span class="dv">1</span>
6262

6363
<span class="kw">def</span> check_data(target):
64-
test_data = [<span class="dv">3</span>, <span class="dv">2</span>, <span class="dv">8</span>, <span class="dv">9</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">7</span>, <span class="dv">5</span>]
64+
test_data = [<span class="dv">3</span>, <span class="dv">2</span>, <span class="dv">8</span>, <span class="dv">9</span>, <span class="dv">3</span>, numpy.nan, <span class="dv">4</span>, <span class="dv">7</span>, <span class="dv">5</span>]
6565
<span class="co"># We look for a zero in the data</span>
6666
index = find_first(test_data, target)
6767
<span class="kw">if</span> index != -<span class="dv">1</span>:
@@ -71,7 +71,7 @@ <h2><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2
7171
<p>The <code>find_first</code> function finds the first occurrence of an element in a list (or an array) of elements and returns its index. The <code>check_data</code> function uses this function to find a certain value in the data and prints the data until that point. It uses some fake “data” and takes an <code>target</code> argument to specify what value to look for.</p>
7272
<p>If we run the <code>check_data</code> function, all looks fine:</p>
7373
<pre class="sourceCode python"><code class="sourceCode python">check_data(<span class="dv">5</span>)</code></pre>
74-
<pre class="output"><code>Data until first occurrence of 5 : [3, 2, 8, 9, 3, 4, 7]</code></pre>
74+
<pre class="output"><code>Data until first occurrence of 5 : [3, 2, 8, 9, 3, nan, 4, 7]</code></pre>
7575
<p>Now let’s run the function again but use a different target value:</p>
7676
<pre class="sourceCode python"><code class="sourceCode python">check_data(<span class="dv">1</span>)</code></pre>
7777
<pre class="output"><code>---------------------------------------------------------------------------
@@ -80,7 +80,7 @@ <h2><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2
8080
----&gt; 1 check_data(1)
8181

8282
&lt;ipython-input-56-610c1db03285&gt; in check_data(target)
83-
16 test_data = [3, 2, 8, 9, 3, 4, 7, 5]
83+
16 test_data = [3, 2, 8, 9, 3, numpy.nan, 4, 7, 5]
8484
17 # We look for a zero in the data
8585
---&gt; 18 index = find_first(test_data, target)
8686
19 if index != -1:
@@ -118,13 +118,13 @@ <h2><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2
118118
<p>To access the data, we can move “up” in the exception stack and investigate the variables there:</p>
119119
<pre class="output"><code>ipdb&gt; up
120120
&gt; &lt;ipython-input-56-610c1db03285&gt;(18)check_data()
121-
16 test_data = [3, 2, 8, 9, 3, 4, 7, 5]
121+
16 test_data = [3, 2, 8, 9, 3, numpy.nan, 4, 7, 5]
122122
17 # We look for a zero in the data
123123
---&gt; 18 index = find_first(test_data, target)
124124
19 if index != -1:
125125
20 print(&#39;Data until first occurrence of&#39;, target, &#39;:&#39;, test_data[:index])
126126
ipdb&gt; test_data
127-
[3, 2, 8, 9, 3, 4, 7, 5]</code></pre>
127+
[3, 2, 8, 9, 3, nan, 4, 7, 5]</code></pre>
128128
<p>To get back to where we were before, we use <code>down</code> or alternatively <code>d</code> (instead of <code>up</code> we can also use <code>u</code>):</p>
129129
<pre class="output"><code>ipdb&gt; d
130130
&gt; &lt;ipython-input-56-610c1db03285&gt;(10)find_first()
@@ -149,7 +149,7 @@ <h2><span class="glyphicon glyphicon-certificate"></span>Learning Objectives</h2
149149
<p>Using a counter and indexing into a list at every iteration of a loop is a often considered to be a so-called “<a href="https://en.wikipedia.org/wiki/Anti-pattern">anti-pattern</a>” in Python.</p>
150150
<aside class="callout panel panel-info">
151151
<div class="panel-heading">
152-
<h2><span class="glyphicon glyphicon-pushpin"></span>Post-mortem debugging with pytest</h2>
152+
<h2 id="post-mortem-debugging-with-pytest"><span class="glyphicon glyphicon-pushpin"></span>Post-mortem debugging with pytest</h2>
153153
</div>
154154
<div class="panel-body">
155155
<p>You can run your test suite with pytest and make pytest open a debugger session for you as soon as an error occurs:</p>
@@ -181,7 +181,33 @@ <h2><span class="glyphicon glyphicon-pushpin"></span>Post-mortem debugging with
181181
(Pdb)</code></pre>
182182
</div>
183183
</aside>
184-
<p>TODO: Exercise</p>
184+
<section class="challenge panel panel-success">
185+
<div class="panel-heading">
186+
<h2 id="error-debugging"><span class="glyphicon glyphicon-pencil"></span>Error debugging</h2>
187+
</div>
188+
<div class="panel-body">
189+
<p>Copy &amp; paste the following code and run <code>test_code_array</code>. It will fail with an error, use the debugger to find out why.</p>
190+
<pre class="sourceCode python"><code class="sourceCode python"><span class="ch">import</span> numpy
191+
<span class="ch">from</span> numpy.testing.utils <span class="ch">import</span> assert_equal
192+
193+
<span class="kw">def</span> code_array(codes):
194+
<span class="co">&#39;&#39;&#39;Store airport codes in an array in numerical form&#39;&#39;&#39;</span>
195+
to_numerical_code = numpy.vectorize(<span class="kw">lambda</span> code: numpy.array([<span class="dt">ord</span>(c) <span class="kw">for</span> c in code]))
196+
<span class="kw">return</span> numpy.vstack([to_numerical_code(c) <span class="kw">for</span> c in codes])
197+
198+
<span class="kw">def</span> test_code_array():
199+
airport_codes = [<span class="st">&#39;TXL&#39;</span>, <span class="st">&#39;LAX&#39;</span>, <span class="st">&#39;PHX&#39;</span>, <span class="st">&#39;CDG&#39;</span> <span class="st">&#39;ORY&#39;</span>, <span class="st">&#39;JFK&#39;</span>, <span class="st">&#39;JNB&#39;</span>, <span class="st">&#39;WAW&#39;</span>]
200+
expected = numpy.array([[<span class="dv">84</span>, <span class="dv">88</span>, <span class="dv">76</span>],
201+
[<span class="dv">76</span>, <span class="dv">65</span>, <span class="dv">88</span>],
202+
[<span class="dv">80</span>, <span class="dv">72</span>, <span class="dv">88</span>],
203+
[<span class="dv">67</span>, <span class="dv">68</span>, <span class="dv">71</span>],
204+
[<span class="dv">79</span>, <span class="dv">82</span>, <span class="dv">89</span>],
205+
[<span class="dv">74</span>, <span class="dv">70</span>, <span class="dv">75</span>],
206+
[<span class="dv">74</span>, <span class="dv">78</span>, <span class="dv">66</span>],
207+
[<span class="dv">87</span>, <span class="dv">65</span>, <span class="dv">87</span>]])
208+
assert_equal(code_array(airport_codes), expected)</code></pre>
209+
</div>
210+
</section>
185211
</div>
186212
</div>
187213
</article>

07-debugging-post-mortem.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def find_first(data, element):
5050
return -1
5151
5252
def check_data(target):
53-
test_data = [3, 2, 8, 9, 3, 4, 7, 5]
53+
test_data = [3, 2, 8, 9, 3, numpy.nan, 4, 7, 5]
5454
# We look for a zero in the data
5555
index = find_first(test_data, target)
5656
if index != -1:
@@ -71,7 +71,7 @@ If we run the `check_data` function, all looks fine:
7171
check_data(5)
7272
~~~
7373
~~~ {.output}
74-
Data until first occurrence of 5 : [3, 2, 8, 9, 3, 4, 7]
74+
Data until first occurrence of 5 : [3, 2, 8, 9, 3, nan, 4, 7]
7575
~~~
7676

7777
Now let's run the function again but use a different target value:
@@ -86,7 +86,7 @@ IndexError Traceback (most recent call last)
8686
----> 1 check_data(1)
8787
8888
<ipython-input-56-610c1db03285> in check_data(target)
89-
16 test_data = [3, 2, 8, 9, 3, 4, 7, 5]
89+
16 test_data = [3, 2, 8, 9, 3, numpy.nan, 4, 7, 5]
9090
17 # We look for a zero in the data
9191
---> 18 index = find_first(test_data, target)
9292
19 if index != -1:
@@ -159,13 +159,13 @@ variables there:
159159
~~~ {.output}
160160
ipdb> up
161161
> <ipython-input-56-610c1db03285>(18)check_data()
162-
16 test_data = [3, 2, 8, 9, 3, 4, 7, 5]
162+
16 test_data = [3, 2, 8, 9, 3, numpy.nan, 4, 7, 5]
163163
17 # We look for a zero in the data
164164
---> 18 index = find_first(test_data, target)
165165
19 if index != -1:
166166
20 print('Data until first occurrence of', target, ':', test_data[:index])
167167
ipdb> test_data
168-
[3, 2, 8, 9, 3, 4, 7, 5]
168+
[3, 2, 8, 9, 3, nan, 4, 7, 5]
169169
~~~
170170

171171
To get back to where we were before, we use `down` or alternatively `d`
@@ -250,4 +250,28 @@ often considered to be a so-called
250250
> (Pdb)
251251
> ~~~
252252
253-
TODO: Exercise
253+
> ## Error debugging {.challenge}
254+
> Copy & paste the following code and run `test_code_array`. It will fail with
255+
> an error, use the debugger to find out why.
256+
>
257+
> ~~~ {.python}
258+
> import numpy
259+
> from numpy.testing.utils import assert_equal
260+
>
261+
> def code_array(codes):
262+
> '''Store airport codes in an array in numerical form'''
263+
> to_numerical_code = numpy.vectorize(lambda code: numpy.array([ord(c) for c in code]))
264+
> return numpy.vstack([to_numerical_code(c) for c in codes])
265+
>
266+
> def test_code_array():
267+
> airport_codes = ['TXL', 'LAX', 'PHX', 'CDG' 'ORY', 'JFK', 'JNB', 'WAW']
268+
> expected = numpy.array([[84, 88, 76],
269+
> [76, 65, 88],
270+
> [80, 72, 88],
271+
> [67, 68, 71],
272+
> [79, 82, 89],
273+
> [74, 70, 75],
274+
> [74, 78, 66],
275+
> [87, 65, 87]])
276+
> assert_equal(code_array(airport_codes), expected)
277+
> ~~~

0 commit comments

Comments
 (0)