Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ba924f5

Browse filesBrowse files
authored
Lecture Review: Major Restructuring of Advanced Python Programming Section, Task 2-3 (#218)
* update * restructure namespace * adding namespace to summary * add link for garbage collection * oop exercise * add a label for boolean data type * fix typos * change title * restructure debugging section * update oop_intro * add visualisations * add images for each line * update debugging chapter * restructure intro to visualisation * fix typos * fix dash * fix indent * update image * update f string * integrate comments * show output * fix typo * clarify comment * update comments
1 parent 76ab162 commit ba924f5
Copy full SHA for ba924f5

File tree

Expand file treeCollapse file tree

8 files changed

+930
-777
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

8 files changed

+930
-777
lines changed
Open diff view settings
Collapse file
198 KB
  • Display the source diff
  • Display the rich diff
Loading
Collapse file
225 KB
  • Display the source diff
  • Display the rich diff
Loading
Collapse file
297 KB
  • Display the source diff
  • Display the rich diff
Loading
Collapse file
249 KB
  • Display the source diff
  • Display the rich diff
Loading
Collapse file

‎lectures/debugging.md‎

Copy file name to clipboardExpand all lines: lectures/debugging.md
+305-8Lines changed: 305 additions & 8 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ kernelspec:
1818
</div>
1919
```
2020

21-
# Debugging
21+
# Debugging and Handling Errors
2222

2323
```{index} single: Debugging
2424
```
@@ -43,9 +43,20 @@ Hey, we all used to do that.
4343

4444
But once you start writing larger programs you'll need a better system.
4545

46+
You may also want to handle potential errors in your code as they occur.
47+
48+
In this lecture, we will discuss how to debug our programs and improve error handling.
49+
50+
## Debugging
51+
52+
```{index} single: Debugging
53+
```
54+
4655
Debugging tools for Python vary across platforms, IDEs and editors.
4756

48-
Here we'll focus on Jupyter and leave you to explore other settings.
57+
For example, a [visual debugger](https://jupyterlab.readthedocs.io/en/stable/user/debugger.html) is available in JupyterLab.
58+
59+
Here we'll focus on Jupyter Notebook and leave you to explore other settings.
4960

5061
We'll need the following imports
5162

@@ -56,11 +67,7 @@ import matplotlib.pyplot as plt
5667
plt.rcParams['figure.figsize'] = (10,6)
5768
```
5869

59-
## Debugging
60-
61-
```{index} single: Debugging
62-
```
63-
70+
(debug_magic)=
6471
### The `debug` Magic
6572

6673
Let's consider a simple (and rather contrived) example
@@ -243,7 +250,7 @@ Then we printed the value of `x` to see what was happening with that variable.
243250

244251
To exit from the debugger, use `q`.
245252

246-
## Other Useful Magics
253+
### Other Useful Magics
247254

248255
In this lecture, we used the `%debug` IPython magic.
249256

@@ -255,3 +262,293 @@ There are many other useful magics:
255262

256263
The full list of magics is [here](http://ipython.readthedocs.org/en/stable/interactive/magics.html).
257264

265+
266+
## Handling Errors
267+
268+
```{index} single: Python; Handling Errors
269+
```
270+
271+
Sometimes it's possible to anticipate bugs and errors as we're writing code.
272+
273+
For example, the unbiased sample variance of sample $y_1, \ldots, y_n$
274+
is defined as
275+
276+
$$
277+
s^2 := \frac{1}{n-1} \sum_{i=1}^n (y_i - \bar y)^2
278+
\qquad \bar y = \text{ sample mean}
279+
$$
280+
281+
This can be calculated in NumPy using `np.var`.
282+
283+
But if you were writing a function to handle such a calculation, you might
284+
anticipate a divide-by-zero error when the sample size is one.
285+
286+
One possible action is to do nothing --- the program will just crash, and spit out an error message.
287+
288+
But sometimes it's worth writing your code in a way that anticipates and deals with runtime errors that you think might arise.
289+
290+
Why?
291+
292+
* Because the debugging information provided by the interpreter is often less useful than what can be provided by a well written error message.
293+
* Because errors that cause execution to stop interrupt workflows.
294+
* Because it reduces confidence in your code on the part of your users (if you are writing for others).
295+
296+
297+
In this section, we'll discuss different types of errors in Python and techniques to handle potential errors in our programs.
298+
299+
### Errors in Python
300+
301+
We have seen `AttributeError` and `NameError` in {any}`our previous examples <debug_magic>`.
302+
303+
In Python, there are two types of errors -- syntax errors and exceptions.
304+
305+
```{index} single: Python; Exceptions
306+
```
307+
308+
Here's an example of a common error type
309+
310+
```{code-cell} python3
311+
---
312+
tags: [raises-exception]
313+
---
314+
def f:
315+
```
316+
317+
Since illegal syntax cannot be executed, a syntax error terminates execution of the program.
318+
319+
Here's a different kind of error, unrelated to syntax
320+
321+
```{code-cell} python3
322+
---
323+
tags: [raises-exception]
324+
---
325+
1 / 0
326+
```
327+
328+
Here's another
329+
330+
```{code-cell} python3
331+
---
332+
tags: [raises-exception]
333+
---
334+
x1 = y1
335+
```
336+
337+
And another
338+
339+
```{code-cell} python3
340+
---
341+
tags: [raises-exception]
342+
---
343+
'foo' + 6
344+
```
345+
346+
And another
347+
348+
```{code-cell} python3
349+
---
350+
tags: [raises-exception]
351+
---
352+
X = []
353+
x = X[0]
354+
```
355+
356+
On each occasion, the interpreter informs us of the error type
357+
358+
* `NameError`, `TypeError`, `IndexError`, `ZeroDivisionError`, etc.
359+
360+
In Python, these errors are called *exceptions*.
361+
362+
### Assertions
363+
364+
```{index} single: Python; Assertions
365+
```
366+
367+
Sometimes errors can be avoided by checking whether your program runs as expected.
368+
369+
A relatively easy way to handle checks is with the `assert` keyword.
370+
371+
For example, pretend for a moment that the `np.var` function doesn't
372+
exist and we need to write our own
373+
374+
```{code-cell} python3
375+
def var(y):
376+
n = len(y)
377+
assert n > 1, 'Sample size must be greater than one.'
378+
return np.sum((y - y.mean())**2) / float(n-1)
379+
```
380+
381+
If we run this with an array of length one, the program will terminate and
382+
print our error message
383+
384+
```{code-cell} python3
385+
---
386+
tags: [raises-exception]
387+
---
388+
var([1])
389+
```
390+
391+
The advantage is that we can
392+
393+
* fail early, as soon as we know there will be a problem
394+
* supply specific information on why a program is failing
395+
396+
### Handling Errors During Runtime
397+
398+
```{index} single: Python; Runtime Errors
399+
```
400+
401+
The approach used above is a bit limited, because it always leads to
402+
termination.
403+
404+
Sometimes we can handle errors more gracefully, by treating special cases.
405+
406+
Let's look at how this is done.
407+
408+
#### Catching Exceptions
409+
410+
We can catch and deal with exceptions using `try` -- `except` blocks.
411+
412+
Here's a simple example
413+
414+
```{code-cell} python3
415+
def f(x):
416+
try:
417+
return 1.0 / x
418+
except ZeroDivisionError:
419+
print('Error: division by zero. Returned None')
420+
return None
421+
```
422+
423+
When we call `f` we get the following output
424+
425+
```{code-cell} python3
426+
f(2)
427+
```
428+
429+
```{code-cell} python3
430+
f(0)
431+
```
432+
433+
```{code-cell} python3
434+
f(0.0)
435+
```
436+
437+
The error is caught and execution of the program is not terminated.
438+
439+
Note that other error types are not caught.
440+
441+
If we are worried the user might pass in a string, we can catch that error too
442+
443+
```{code-cell} python3
444+
def f(x):
445+
try:
446+
return 1.0 / x
447+
except ZeroDivisionError:
448+
print('Error: Division by zero. Returned None')
449+
except TypeError:
450+
print(f'Error: x cannot be of type {type(x)}. Returned None')
451+
return None
452+
```
453+
454+
Here's what happens
455+
456+
```{code-cell} python3
457+
f(2)
458+
```
459+
460+
```{code-cell} python3
461+
f(0)
462+
```
463+
464+
```{code-cell} python3
465+
f('foo')
466+
```
467+
468+
If we feel lazy we can catch these errors together
469+
470+
```{code-cell} python3
471+
def f(x):
472+
try:
473+
return 1.0 / x
474+
except:
475+
print(f'Error. An issue has occurred with x = {x} of type: {type(x)}')
476+
return None
477+
```
478+
479+
Here's what happens
480+
481+
```{code-cell} python3
482+
f(2)
483+
```
484+
485+
```{code-cell} python3
486+
f(0)
487+
```
488+
489+
```{code-cell} python3
490+
f('foo')
491+
```
492+
493+
In general it's better to be specific.
494+
495+
496+
## Exercises
497+
498+
```{exercise-start}
499+
:label: debug_ex1
500+
```
501+
502+
Suppose we have a text file `numbers.txt` containing the following lines
503+
504+
```{code-block} none
505+
:class: no-execute
506+
507+
prices
508+
3
509+
8
510+
511+
7
512+
21
513+
```
514+
515+
Using `try` -- `except`, write a program to read in the contents of the file and sum the numbers, ignoring lines without numbers.
516+
517+
You can use the `open()` function we learnt {any}`before<iterators>` to open `numbers.txt`.
518+
```{exercise-end}
519+
```
520+
521+
522+
```{solution-start} debug_ex1
523+
:class: dropdown
524+
```
525+
526+
Let's save the data first
527+
528+
```{code-cell} python3
529+
%%file numbers.txt
530+
prices
531+
3
532+
8
533+
534+
7
535+
21
536+
```
537+
538+
```{code-cell} python3
539+
f = open('numbers.txt')
540+
541+
total = 0.0
542+
for line in f:
543+
try:
544+
total += float(line)
545+
except ValueError:
546+
pass
547+
548+
f.close()
549+
550+
print(total)
551+
```
552+
553+
```{solution-end}
554+
```

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.