Prime Number Generation¶
Intro¶
Error handling is essential for any programmer. Being able to understand error messages and quickly apply accurate fixes is vital for mental health. Unfortunately, Python’s stack traces don’t always give a clear picture of everything that can go wrong…
Working Through an Example¶
Let’s go through an example where we create a function to identify prime numbers, and then generate random numbers until we find a prime number validated through our function.
Exercise¶
Take a look at the example in random_prime_number.py
: do you see any errors in the code?
1import random
2from math import sqrt
3
4
5def is_prime(number, *, _factor=None):
6 """
7 Check whether the given number is prime.
8
9 Returns:
10 True if prime, False if composite.
11 """
12 # If we weren't called recursively, generate the initial factor to check
13 if _factor is None:
14 _factor = int(sqrt(number)) + 1
15
16 # Prime number must be integers
17 if type(number) is not int:
18 return False
19
20 # If we reached 1 without finding another divisor, it's prime!
21 if _factor == 1:
22 return True
23
24 # If any other factor evenly goes into the number, it is not prime
25 if number % _factor == 0:
26 return False
27
28 # Recursively check with smaller factor
29 return is_prime(number, _factor=_factor - 1)
30
31
32def generate_num():
33 """
34 Generates a random integer
35
36 Returns:
37 A 2-tuple containing the randomly generated number
38 and whether or not it's prime.
39 """
40 number = random.random()
41 return number, is_prime(number)
42
43
44def main():
45 # Keep generating random numbers until we find a prime.
46 number, prime = generate_num()
47 while not prime:
48 number, prime = generate_num()
49
50 print(f"The prime number generated is: {number}")
51
52
53if __name__ == "__main__":
54 main()
Take a guess, and then confirm by running the program. Does it work as you expected? If not, is it obvious why your program is not running properly?
Expectations vs Reality¶
Often an exception is thrown and the stack trace Python prints allows a quick solution to become
apparent, but sometimes we get no feedback at all. In this case, we accidentally entered an infinite
loop! But where in the program did we go wrong? Does the logic in the function is_prime
work
correctly, or is the error somewhere else?
Since the code enters an infinite loop, Python never gives us a stack trace. This can lead to a lot of confusion and no information as to where the error occurred. We’re here to see if there is a better way to debug your infinite loop.
Challenge¶
Use pystack
on the running program and see if you can identify the bug. Be sure to check what
options may help you locate the errors in your code.
Hint 1
Check your local variables using pystack
.
Hint 2
Try the following command while your program is running: pystack remote --locals {PID}
.
Solutions¶
Toggle to see the solution
After using PyStack and printing the locals you can see that we accidentally used the wrong random
function! In our current implementation, random.random()
only returns floats between [0.0, 1.0).
Our is_prime
function has correct logic, but the function will never get passed a prime number,
because of the random number generator we chose!
1def generate_num():
2 """
3 Generates a random integer
4
5 Returns:
6 A 2-tuple containing the randomly generated number
7 and whether or not it's prime.
8 """
9 number = random.random()
10 return number, is_prime(number)
A quick fix is to replace the random.random()
call with random.randint(0, 100000)
. With this
quick fix, our program will now generate random prime numbers!
Conclusion¶
Sometimes, finding the bug in your code is not as simple as looking at a stack trace. Infinite loops are common logical errors in programs, but can be difficult to find. Instead of spending excessive time searching through lots of code, using PyStack can help you find these logical errors.