08-Debugging
Contents
08-Debugging#
Errors
Syntax
Exceptions
Debugging Process
Stack trace
Using outside resources
try
/except
Logistics#
Wed Jan 30:
CL4
Fri Feb 2:
~~Exam 1 in class component~~ ONE WEEK LATER!
A2
Mon Feb 5
~~Exam 1 take home component due~~ ONE WEEK LATER!
Exam info
in class component
will largely be multiple choice and short answer
will largely test your understanding of code, not ask you to write it
will test your knowledge of concepts and jargon and code style
no notes or cheat sheet allowed
paper or Canvas (uncertain which right now)
take home component
will look like an assignment, on Datahub
will ask you to create code to solve problems
open notes
do not seek help from an AI or a person
Practice exam will be availble or we will use Wed lecture / coding labs to review (uncertain which right now)
Errors#
Syntax Errors#
Syntax Errors
Indentation Errors
Syntax Error Examples#
# will produce a syntax error
if True
print('Yep.')
Python does its best to tell you:
what type of error it is
and where it thinks it occurred (
^
)
# will produce a syntax error
# and specifically an indentation error
del value
if 3 < 5:
print(value)
Python gives you a readout about what it was expecting and where you appear to have gone wrong.
Exceptions#
For these, there’s nothing wrong with the syntax or structure of the code, but in your specific case and how you’re trying to use it, Python says ‘no’.
ZeroDivisionError#
ZeroDivisionError occurs when you try to divide by zero.
# produces ZeroDivisionError
1 / 0
Python specifies:
the Exception and specific type / error
points you to where the error occurred
NameError#
NameError occurs when you try to access a name that Python does not know.
# Define a variable
variable = 12
# If you typo a name, you will get a NameError
varaible
While it’s annoying, it’s helpful that Python doesn’t just guess that you meant ‘variable’….because sometimes Python would guess wrong. It’s better for Python to just give us the error.
# You also get a name error if you try to use the wrong operator for assignment
new_variable == 1
IndexError#
IndexError occurs when you try to access an index that doesn’t exist.
my_string = 'COGS18'
my_string[6]
# Relatedly, 'KeyError' occurs if you ask for a dictionary key that doesn't exist
my_dictionary = {'name1' : 1, 'name2' : 2}
my_dictionary['name3']
ValueError#
ValueError occurs when you try to use an illegal value for something.
int('cat')
TypeError#
TypeError occurs when you try to do something with a variable type that python cannot interpret.
'a_string' + 12
Error Recap#
Syntax Errors
SyntaxError
IndentationError
Exceptions
ZeroDivisionError
NameError
Index Errors
IndexError
KeyError
ValueError
TypeError
Class Question #1#
What type of error will the following code produce?
if num > 0
print("Greater than 0")
A) Syntax
B) Name
C) Type
D) Index
E) Value
Class Question #2#
What type of error will the following code produce?
if num > 0:
print("Greater than 0")
A) Syntax
B) Name
C) Type
D) Index
E) Value
Stack Trace#
Read (and understand!) your error messages!
The trace (log) of what Python did as it went through your code. Gets printed out if Python runs into an error.
For example…say you’re trying to write a function that takes a character as input, turns it into its unicode code point…with an offset of 500, turns that back into a character and returns the output…Your first attempt (which has errors) is below:
def encode_char(char):
# turn into code point
ord(char)
# add offset
char + 500 = offset
# turn into character
chr(offset)
What to look for and think about:
What kind of error is it?
What line of code/where in the line of code is the error pointing to?
What does it mean? How do I fix this?
Sometimes these get really complex. We’re here to get better at interpreting these traces. Note that if external functions are being used, these will get longer.
Sometimes you even have assert
messages to guide you…how should you use assert
messages?
Read them; understand them
Revisit the part of your code most likely associated with the assert
Think about what you would need to change to fix the issue (do not just guess wildly trying to pass the
assert
- will waste your time)Fix the code; re-execute; re-run the assert
assert callable(encode_char)
assert type(encode_char('c')) == str
assert encode_char('c') == 'ɗ'
Helping yourself when debugging#
Pause and think
You aren’t sure how to approach a problem: add ‘in python’
You don’t understand an error message:
Use
print()
statementsGoogle the error message…but then you need to understand what you’re reading
Unsure how to approach a problem?#
“Write code that will check whether the value stored in my_val
is both positive and even. If it is, store the integer 1
in the variable output
”
…How do I check whether a variable stores an even value?
Google: “How to check whether a variable stores an even value in python”
ChatGPT: How would I write a function in python to determine whether a variable stores an even value?
Don’t understand the error message?#
So you try to accomplish the task…below is your first attempt
# this code has errors
# we're going to debug together in class
my_val = 6
if my_val > 0 and my_val % 2 = 0:
output == 1
Try / Except#
try
and except
.
For this example, I’m going to introduce input()
, a function which allows us to get input from the user.
# Example: we want to get an input number from the user
my_num = input("Please type a number: ")
print('\nmy_num is: ', my_num)
try
/ except
Block#
try:
int(input('Number'))
except:
print("nahhh")
Raising Errors#
Raise Exception Examples#
raise
is a keyword that tells Python you want to create your own error.
my_int = input('An integer please: ')
if not my_int.isnumeric():
raise ValueError('I wanted a number! :(')
print('My integer is: ', my_int)
Class Question #3#
Edit the code below (replacing ---
with either values or variable names) so that when executed, this cell returns None
.
num1 = ---
num2 = ---
try:
output = num1 / num2
except ZeroDivisionError:
output = None
print(output)
A) I did it!
B) I think I did it…
C) I’m totally lost.
Debugging a program#
Before you start debugging, make sure you’ve identified the problem you’re trying to solve:
What did you expect your code to do?
What happened instead?
It might even be helpful to write these things down!
In making explicit what you expected your code to do, you have stated some assumptions. The next natural step is to test each and every one of those assumptions.
Typical assumptions you might make are:
A particular function you are using (e.g.
math.pow
) works with two arguments in a certain order (e.g., exponent, number)A particular variable will have value I expect (e.g. a number between 1 and 10)
I have made no typos in my code
The bug only appeared after I edited function X… therefore the problem must be in the changes I made to function X
The reason we test assumptions is because they MAY NOT BE TRUE. All of the things in the list above are all things I assumed while programming that turned out to be wrong. It is important to remember how Sherlock Holmes solves cases
When you have eliminated the impossible, whatever remains, however improbable, must be the truth
To test your assumptions you must set out to prove them wrong. Do not try to show your assumptions are correct… set out to show they are wrong.
Some advice for testing your assumptions#
Check suspect code line by line to look for syntax error style problems (the wrong ‘ or “, missing brackets, bad indentation, a typo in a variable name).
Look 2 or 3 times at program control points (if statements). Is the condition actually what you intended/assumed? E.g., you might have accidentally assigned a student an A if they scored >89%… the correct would be >=90%.
Use
print()
! Print out variable values at different points in the program to make sure they return what you expect. Watching a variables value change as you execute the program can show you that something unexpected is occurring at a particular point in the program… leading you to finally see the typo or bad logic at the heart of the problem.Read the error output in the terminal. It tries to be helpful, but it will often not quite point you towards the problem. It can at least give you a ballpark location in the code and some things to look for.
Get sections of the code working one by one. If you are sure that section A is bug free, you can narrow your search for the problem to section B or C.
Read the Python documentation for the methods you are employing.
Comments throughout your code to make sure you understand what every step is doing. This will help you pinpoint problems.
Ask for help! Working with an expert to debug is going to make your debugging skills take flight.
# Here's an exercise for you to debug. Apply your new skills!
greeting = input("Hello, possible pirate! What's the password?)
if greeting in ["Arrr!"):
print("Go away, pirate.")
elif
print("Greetings, hater of pirates!")
# Here's an exercise for you to debug. Apply your new skills!
# hint, maybe you want to print out the contents of out
# after every line of code to see how it changes
def string_spinner(a_string):
'''
string_spinner
input: a_string (any string)
output: the same string but backwards and with Spanish-style ¡ and ! added front and back
'''
out = a_string
a_string = a_string[::-1] # this reverses the string
return '¡'+out+'!'
# this should print
# '¡ogge ym oggel!'
# but it doesn't
string_spinner('leggo my eggo')