Skip to content

Debugging

agraca edited this page Jan 1, 2018 · 9 revisions

Overview

Bram Cohen, the creator of BitTorrent, wrote "90% of coding is debugging. The other 10% is writing bugs". Even amongst Computer Science college students, there is the belief that suffering through the debugging process is inevitable in any programming project. Here in Ignite, we have just a simple suggestion; get good.

There is nothing inherent with coding that creates bugs. Computers do exactly what you tell it to do. Although bugs will happen, it is possible to control the frequency and severity of them. Our biggest recommendation to preventing bugs is to actually take out a sheet of paper and write down a roadmap of the logic you want your program to follow. You can then break down the problem into easy, bite-sized chunks.

Python also has some tools that help you determine exactly what your program is doing and where it is going awry. We will be exploring those tools and they may hopefully help you The earlier you catch bugs, the easier they will be to fix.

We will learn how to:

  • Deal with unexpected issues gracefully with Exceptions

  • Uncover logic bugs quickly from sanity checks with Assertions

  • A more systematic way of checking variables with Logging

New Concepts

Syntax Errors

Syntax errors are the most common errors while one is learning Python. The way to read Syntax Errors is to determine what line the error is occurring at and find the error before the little arrow. In this case, the syntax error is caused by missing a colon (:) for the while statement.

>>> while True print('Hello world')
  File "<stdin>", line 1
    while True print('Hello world')
                   ^
SyntaxError: invalid syntax

Exceptions

Even though code may be syntatically correct, it still may cause an error when the Python interpreter tries to run it. Exceptions are usually used in cases where your program is expecting user input and the user may input something you do not expect. This allows you to solve errors gracefully instead of crashing

>>> 5/0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

Handling Exceptions

It is possible to handle exceptions so that your program can recover so that your program knows how to deal with these errors instead of crashing fantastically. This is done with the try-except block.

while True:
 numerator = int(input('Please enter a numerator: '))
 denominator = int(input('Please enter a denominator: '))
 try:
   print(str(numerator/denominator)) 
 except ZeroDivisionError:
   print('You cannot divide by zero. Try again...')

If there are no problems with the code, the try block runs normally. If there is a problem inside of the try block, Python will jump straight to the except block. An except block can take a tuple containing multiple exception types.

Raising Execeptions

Exceptions are useful because they tell us exactly what's wrong with our program with a handy error message. There are scenarios where we would want to create or raise our own exceptions.

Let's say I want to count the number of jelly beans I have, it doesn't make any sense to have a negative number of jelly beans. Let's make an exception.

Jelly Bean Example

Output:

How many Jelly Beans do you have? 1
How many Jelly Beans do you have? -1
An exception happened: Jelly Beans cannot have a non-negative number. Re-enter
How many Jelly Beans do you have? 4

In order to create a raise statement, we will need

  • The raise keyword

  • A call to the Exception() function

  • A string that details the error

Assertions

One of the big problems with coding is that some logical bugs are hard to find. An assertion is a sanity check for the programmer to make sure that your code isn't doing anything it should not be doing. This is done with an assert statement. When your code fails an assert check, then an AssertionError exception is raised. You can think of an assert statement as, "I assert that this condition is true, if it is not then something is terribly wrong in the program

To create an assert statement, we will need

  • The assert keyword

  • A condition that evaluates to either True or False

  • A string to display when the condition is False

I always get paranoid if I lock my door when I leave my house. I can assert that my door should be locked when I leave my house

lockedDoor = False

def leaveHouse():
  lockedDoor = True

print('I am going to leave my house')
assert lockedDoor == True, 'You did not lock your doors before leaving!'
# Now I know to lock my door and I can hard code for it

You are not supposed to handle assert exceptions. The goal is to force the program to crash so you can fix the logic bug. Failing in this manner is good because it will allow you to fix the problem quickly instead of noticing it later down the line, with much headache.

Logging

Clone this wiki locally