Developing the basics : Programming myself, post three
Debugging
<< Read the previous post in this series Read the next post in this series >>
So if like me you are preferring to really get your hands dirty with the code and trying out things beyond what the exercises are asking you to do, then the chances are you are needing to fix a lot of problems with your code, to make it work as you would expect. In programming this is known as debugging.
There are essentially three things that can go wrong with your code. The interpreter doesn’t understand what you’re saying and so doesn’t know what to do, and then cries about it. Remember, computers speak a very formal language. This would be like trying to talk cockney slang to the Queen after you have been drinking – chances are you will get savagely beaten by some of her personal bodyguards, saying the wrong thing in the wrong context is known as a syntax error, you can remember this by thinking its a sin to tax the queen. If you are using a good IDE like PyCharm chances are you will get warned about the problems before you try to run them.
The next type of error happens only when you run the code. They often come with some description in the console of what went wrong, your code seems fine, but somehow the interpreter is running into trouble. These are called runtime errors. It can cause the interpreter to hang or even do nothing or better throw an exception. To remember the name for them you can simply think of them as “not running” errors.
The final type of error is where you get a result, everything seems to be working right, but it is not the result you actually were hoping for, or what you want, kind of like when Columbus sailed to India the wrong way and hit the Americas – not really what he was expecting, probably. So like the seaman making poor choices, these are semantic errors. You can always call the output a feature, as technically the program works and if you haven’t been commenting the code then who is to know that what you have made wasn’t really supposed to work this way?
When errors come about, especially if you are making a lot of progress, this can be the worst. There are some things to be aware of:
The first is stay positive. It’s a puzzle and not the end of the world and once it is cracked you have something that is totally yours. If you are copying someone else’s example this is still true… but the error is probably because they have written their code example in python 2, and you have python 3 (this has caught me out more times than I am proud of).
What is important in each of the cases is first to work out what kind of error you have,
Syntax Errors
The syntax errors are usually the easiest, the IDE will normally tell you what’s wrong. Comment out the code inside and try a hello world print to check what you are running is the correct thing.
Make sure you have the :(colon) after any – for, while, if and def statements.
Make sure your variables are single strings_like_this
and not strings like this
.
Make sure you don’t use a keyword to name a variable.
Check that things are closed ([{“ all need to be closed on the other side in the right order too”}]).
Check your indentations are right for the statements.
Finally, you use the correct operand == and not = for conditionals.
PyCharm will resolve pretty much all these issues.
Runtime Errors
Runtime errors are a bit harder, because it is at least running then it isn’t a syntax issue. The things to look at are how you are using your functions and if you have any loops in your code as these seem to be the most likely culprits. There is normally some kind of message to go along with it.
NameError – your variable doesn’t exist, this can be if you have a declared variable in a function. If you want a variable to be global you have to declare it outside of a function.
Def password():
Password = “12345Pass”
Won’t let you then use this in a second function.
Better is just to declare the variable out of a function
Password = “12345Pass”
TypeError – If you think that everything by default is a string, you can’t go far wrong. Strings cannot add or subtract or do any operand type calculations. Ints and floats can, so you must make sure that your interpreter knows the string is a number. Numbers with decimal points can be added to numbers which don’t have decimal points, so make sure that you tell the interpreter that they are dealing with numbers with decimal points if they have them.
KeyError – if you try to use something in a dictionary make sure it contains it.
IndexError – are you trying to call on something that is bigger than the array it is stored in?
AttributeError – the attribute or method you are calling doesn’t exist. Make sure your functions are returning something to read. Or else it will be none and the response you get is the Attribute error.
Semantic Errors
Semantic errors can be hard to work out, especially if you are not completely clear on exactly what you expect to get back – the answer to a really ridiculously hard calculation for instance.
You need to look through the code in any case and run it through bit by bit and look if something happening to the results you didn’t expect, or was there something you did expect the code to do but didn’t? Again your first call should be the functions you have, put in a few print functions before and after the functions to see how the result is changing. You can also use a technique known as stepping which will allow you to follow the code through step by step. This should show you at least where your result is deviating in a way which you don’t want it to.
So let’s have a look at this in action.
First the very simple program “what is the meaning of life” from last week.
So everything works right. If I put in the number 42 then it returns “Yes now go forth and prosper!” If I put in a number higher or lower it will also print out some kind of text.
But… if I type in some kind of text into the answer on my command, it “unleashes hell”.
OK, so we can now go through this. It isn’t a syntax error, because it runs and compiles fine.
It could be a runtime error as 1, it returns an error and 2, it happens when running the code. And it isn’t a semantic error as it does not return anything strange – apart from the error message and the crash of the console.
Let’s take a look line by line and see what can be worked out from the response:
What is the meaning of life?: There is no meaning, life is pain
Ok so the input from me was a string not a number. Probably a little darker than it could be, changing it to “life is beautiful and full of buttercups” though still throws an error.
Traceback (most recent call last):
File “C:/Users/david/PycharmProjects/SandboxTesting/testing stuff.py”, line 5, in <module>
guess = int(g)
Line 5 – guess = int(g) this seems to be the cause of all the problems. We are making sure the variable is of type int, which means integer, which means number, but we are not putting a number in there. Ok, it’s pretty clear that this is a problem.
ValueError: invalid literal for int() with base 10: ‘There is no meaning, life is pain’
This text seems to be in English, but written in a way only incredibly clever people can understand. Google can probably put this into normal words – The error is “invalid literal for int() with base 10:”. This just means that the argument that you passed to int doesn’t look like a number. In other words it’s either empty, or has a character in it other than a digit.
Process finished with exit code 1
Exit code 1 = bad. You always want your programs to exit on a 0.
So from all this we can basically work out it is because we are converting to an integer, but we have a string in the first place so it doesn’t work.
What we need to do then is somehow give an option for it to still run even if someone has typed in some text rather than numbers.
So I will add in a “try” method and if it creates a value error, then it will simply print “No! Come on it’s a number”
Hmm, now there is a syntax error. What is going on here then?
If I hover over the red squiggles in the IDE, it is saying “statement expected found: py:EXCEPT_KEYWORD”
Adding more excepts does nothing to help this, deleting it means the issue is the same.
Now it is time to “rubber duck” the code – what this basically means is you need to walk through the code logically and try to talk your way through the problem. It’s called rubber duck debugging because if you talk to yourself you come across as mental, so it is better to have a rubber duck on your desk to talk to.
My conversation went a little (exactly) like this:
“What the bloody bugger is going on here”
“…”
“Ergh what is this except value error doing?”
“…”
“You’re right it’s not really getting used right.”
“…”
“What do you mean it could be indented wrongly, it is part of the try part”
“…”
“Should it be indented the same as the try?”
“…”
“You know nothing Jon Snow”
“…”
“Ok, ok I will try it out”
“…”
“Good job, I’m sorry I called you Jon Snow”
“…”
“Shut up duck”
So by going through and thinking about the different aspects of the code, I was able to realize that the except ValueError code was indented too far. A quick delete to put it in line, and we are cooking with kerosene.
And that is how you debug your code to make it work, the way you want/expect/need it to. If you have been doing a lot of debugging, I hope this has inspired you to get a rubber duck or inanimate toy to direct your fury toward.
Also, you might have noticed I have a dark theme for my PyCharm Edu, not only does this look cool, it makes you cool. To do this go to File >> Settings >> Appearance & Behavior and select the Darcula theme.
Programming allows you to think about thinking, and while debugging you learn learning – Nicholas Negroponte