Become a Bug Bounty Hunter
Speaking of hitting a bug, it’s inevitable once you start writing complex programs that you’ll run into bugs in your code. It happens to all of us! Don’t let bugs frustrate you. Instead, embrace these moments with pride and think of yourself as a bug bounty hunter.
When debugging, it’s important to have a methodological approach to help you find where things are breaking down. Going through your code in the order in which it is executed and making sure each part works is a great way to do this.
Once you have an idea of where things might be breaking down, insert import pdb; pdb.set_trace()
into your script and run it. This is the Python debugger and will drop you into interactive mode. The debugger can also be run from the command line with python -m pdb <my_file.py>
.
00:00 Become a Bug Bounty Hunter. Bugs are an integral part of programming. Once you move beyond even the simplest program that you create, you’ll no doubt encounter this.
00:15 It can be a frustrating part of the learning experience, but you’ll often find it will also be the most rewarding and will teach you the lessons you know the best.
00:25 Remember: nobody creates code without bugs. The key to finding bugs is to be methodical. It’s no use just randomly trying to change things. It’s much better to try and get in the mind of what the computer is trying to do, and seeing if it really is doing what you think it’s doing.
00:44 Many has been the time when it’s looked like it’s kind of doing what I think, but actually when I’ve looked at the details of it, maybe I’ve got lucky and actually it’s much less like what I originally planned.
00:56 We’re going to look at two ways of solving these issues. Firstly, the old school way, favored by Guido van Rossum, is using print statements, so now you’re going to see that in action.
01:11 The program I’m going to create is fairly simple and also you may well spot the bug that’s present in it, but the idea is really to create a program which is simple to understand, rather than create an esoteric, difficult-to-find bug. Don’t worry—you’ll have plenty of those to deal with later on.
01:28 So, you’re just going to see a simple number guessing game. The computer is going to think of a number between 1 and 10, then the user has to guess it, and then the computer will tell the user whether they got it right or not.
01:40
So, here comes the code. I’m going to import the random
library to allow us to generate a random number… print a message for the user…
02:00 create the random number…
02:13
and now we’ll let the user input their guess and assign that to the guess
variable. Now we’re going to check if the guess
is the same as the number
, and if it is, we will tell them they were right.
02:47 And if it’s not, we will tell them they were wrong.
03:06 There we go. The program’s complete, and now you’re going to see it in action.
03:19 So, I’m just going to keep running it until the bug makes itself known to us.
03:38
And there, after many more times than you might’ve expected—but that’s the nature of randomness—we see our bug. It’s saying, Sorry, the number was 5, not 5
.
03:51
So up to this point, you might have thought your program was working fine. You could have shown it to somebody and been happy about it, and then somebody is going to say, “Hang on a minute. It said the number was 5, not 5
, what’s the problem there?” So what we need to do is to use a print statement to help us find out what the problem is.
04:12 I’m going to insert one here…
04:30 and now when we rerun the program…
04:41 what we’ve just printed out, in this case, isn’t going to help us too much, because it’s not the representation that’s the problem—it’s the actual information. So let’s look a little deeper.
05:13
So here, we’re going to look a little deeper at this and look at what the type is of number
and guess
.
05:33
And there we see the problem. The problem is that our number
is an int
—because it’s been created by random.randint()
—but our guess
is a str
(string), and when we print str
s or int
s out, they look identical to us onscreen.
05:48
You may have noticed that wouldn’t be the case if you’re doing this kind of work in the Python REPL, so it’s important to realize that print()
may not always show you all of the information you need to find subtle bugs such as this, but it can be a really useful and quick method to find out what’s going on when a program is running. So in this case, to fix this particular bug, the input needs to be turned into an int
.
06:16
Now, this would fail if the user types something which can’t be turned into an int
, but in this case, we’ll just leave it as it is to keep it nice and clear.
06:23
So now, when we run the program again, we can see they are both int
, and if I run it enough times to get the guess right…
06:45
finally, we get to a point where the guess
was 5
, the number
was 5
, and we can see the program works as intended.
06:54
Having seen print()
in action, next—pdb
, the Python debugger. So onscreen, you can see the buggy number guessing program from the previous section, and we’re now going to import pdb
to allow us to use it to debug this program.
07:21
So, I’ve imported pdb
at the beginning, and at the point where I want pdb
to take over the execution of the program, I put the following line: pdb.set_trace()
. So as you’ll see, the program will run normally until it gets to this point, and then we’ll be able to take over step-by-step execution, and it’ll allow us to look around inside the program as it’s still running in memory.
07:54
So, I get to enter the number normally, but now you can see, it looks quite different. The (Pdb)
line at the left shows us that pdb
has taken over the execution of the program. Now, it’s really easy to forget where you are in a program, so one of the key instructions to use is l
, for list.
08:15
We can see it’s showing us a section of the program—in this case, it’s saying we’re at line 7, and the next instruction is going to be if guess == number:
.
08:25
But what we can do right now is look at what’s in the computer’s memory. And it’s much like a normal Python shell. If I type number
, we can see the value of number
.
08:43
If I type guess
, we can see the value of guess
, and straight away, this has worked a little better than print()
, because it’s indicating to us that this isn’t an int
—it’s a string. So with this one command, we’ve already found what the problem is, whereas with print()
, we needed to delve deeper and manually print out the type of the variables in question.
09:08
But let’s just let the program move on, and we can do that with c
, for continue. And you see, it runs to the end, it’s illustrating that it works normally—Sorry, the number was 8, not 5
—and because this is a small, simple program, that’s all we need to do. Now, if we put the trace in a different place, we could cheat.
09:31 Let’s take a quick look at that.
09:40
So now, I’ve put it before I need to put my guess
in, so I can cheat—I can look inside the computer’s mind, see what it’s picked, and then put that number in, which sometimes will be useful to allow you to not have to run the program 10, 15, 20 times, et cetera.
10:01
Let’s see what number
is. We can see number
is 9
. So now, I can continue. It’s asking for input, so I’ll type in the number 9
and we get the bug Sorry, the number was 9, not 9
.
10:17
Now again, this is really easy to fix, as you’ve seen in the previous video, but the idea of this was to give you an idea of how you can use pdb
, but also that pdb
can be really flexible because you don’t have to type out a load of print statements. You can just effectively pause time, look around the computer’s memory, and work out what’s going on without having to put 20 print statements in. You can step through the program and examine variables each time it comes around.
wayne2056 on March 27, 2020
Nice.. I didn’t know about PDB or breakpoint() <— Newbie
Miguel Armando Andrade on June 21, 2020
Its very important NOT to name your python file as a reserved word, in my case i named my file random.py which prevent me from running it. receiving weird errors. Take this into consideration.
CG-Tespy on Nov. 22, 2022
The best attitude to take towards bugs is this: stepping stones to success. Perhaps even signposts pointing to success as well.
Yuvaraj0807 on Jan. 7, 2023
Good to know the procedure and this PDB is new for me. Let see in further lessions.
Maroua Gasmi on March 7, 2023
Intresting presentation. No matter how much I think I know about code, there are always good practices that make life easier. However, I wish these presentations had graphics and animations instead of just bullets that would help retain more information.
Become a Member to join the conversation.
herepete on Aug. 7, 2019
It might be worth mentioning in Python3.7 using breakpoint() is a easier to type and use than import pdb , pdb.set_trace()