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.