Finding prime numbers is one of those classic coding challenges that every developer encounters early in their career.
I remember the first time I had to write a script to filter a massive list of ZIP codes to find “prime” delivery zones for a logistics project in Chicago.
Prime numbers are integers greater than 1 that have no divisors other than 1 and themselves.
In this tutorial, I will show you exactly how to find these numbers within a specific range using Python.
Find Primes Using a Basic For Loop
The simplest way to tackle this is by using nested loops.
I often use this approach when I’m working on a small script where readability is more important than blazing-fast performance.
In the example below, we iterate through a range of numbers (let’s say we are looking at population density figures for small towns in Oregon) and check each one.
def find_primes_basic(lower, upper):
prime_list = []
for num in range(lower, upper + 1):
if num > 1:
for i in range(2, num):
if (num % i) == 0:
break
else:
prime_list.append(num)
return prime_list
# Example: Prime numbers between 10 and 50
print(find_primes_basic(10, 50))I executed the above example code and added the screenshot below.

The logic here is simple: for every number, we try dividing it by every integer from 2 up to the number itself.
If any division leaves no remainder, we “break” the loop because it’s clearly not prime.
Optimize with the Square Root Property
As I gained more experience, I realized that the basic loop does a lot of unnecessary work.
Mathematically, if a number $n$ has a factor, one of those factors must be less than or equal to the square root of $n$.
I started using this optimization years ago while building an inventory system for a tech firm in San Francisco to speed up data validation.
import math
def find_primes_optimized(lower, upper):
prime_list = []
for num in range(lower, upper + 1):
if num <= 1:
continue
is_prime = True
# Only check up to the square root of the number
for i in range(2, int(math.sqrt(num)) + 1):
if (num % i) == 0:
is_prime = False
break
if is_prime:
prime_list.append(num)
return prime_list
# Example: Primes in a range of ID numbers
print(find_primes_optimized(100, 200))I executed the above example code and added the screenshot below.

By stopping at the square root, you drastically reduce the number of iterations, especially as the numbers get larger.
Use the Sieve of Eratosthenes for Large Ranges
When I need to find primes in a massive range, like identifying unique serial numbers across a nationwide database, I reach for the Sieve of Eratosthenes.
This is an ancient algorithm that is incredibly efficient because it “marks” non-prime numbers instead of testing each one individually.
It works by starting at 2 and crossing out all of its multiples, then moving to the next available number and repeating the process.
def sieve_of_eratosthenes(limit):
prime = [True for _ in range(limit + 1)]
p = 2
while (p * p <= limit):
if (prime[p] == True):
for i in range(p * p, limit + 1, p):
prime[i] = False
p += 1
return [p for p in range(2, limit + 1) if prime[p]]
# Example: Finding primes up to 500 for a data science project
print(sieve_of_eratosthenes(500))I executed the above example code and added the screenshot below.

This method is significantly faster for large ranges because it avoids repeated divisions.
Use the SymPy Library
If you are working in a professional production environment, you might not want to reinvent the wheel.
In my recent projects involving cryptographic checks for a financial app in New York, I simply used the SymPy library.
It is a specialized library for symbolic mathematics that has a highly optimized primerange function.
from sympy import primerange
def get_primes_sympy(lower, upper):
# primerange(a, b) provides primes in the range [a, b)
return list(primerange(lower, upper + 1))
# Example: High-performance prime range detection
print(get_primes_sympy(10, 100))This is the cleanest approach if you are allowed to add external dependencies to your project.
Full Example: Interactive Prime Finder
Here is a complete, runnable script that combines these concepts.
I’ve designed this to handle user input, which is a common requirement for command-line tools I’ve built for various US-based clients.
import math
from sympy import primerange
def get_user_primes():
print("--- US Real Estate Data Validator: Prime Lot ID Finder ---")
try:
lower = int(input("Enter the starting ID: "))
upper = int(input("Enter the ending ID: "))
if lower > upper:
print("Error: Starting ID must be less than Ending ID.")
return
# Using the optimized square root method for general use
primes = []
for num in range(lower, upper + 1):
if num > 1:
for i in range(2, int(math.sqrt(num)) + 1):
if (num % i) == 0:
break
else:
primes.append(num)
print(f"\nFound {len(primes)} prime IDs in the range {lower} to {upper}:")
print(primes)
except ValueError:
print("Invalid input. Please enter whole numbers.")
if __name__ == "__main__":
get_user_primes()In this guide, I’ve shared the different ways I’ve handled prime numbers throughout my career.
Whether you need a quick loop for a small script or a powerful Sieve for a large-scale application, one of these methods will get the job done.
You may also like to read:
- Python Return Statement
- Validate Passwords in Python
- Get the Day of the Week from a Date in Python
- Validate Email Addresses in Python

Bijay Kumar is an experienced Python and AI professional who enjoys helping developers learn modern technologies through practical tutorials and examples. His expertise includes Python development, Machine Learning, Artificial Intelligence, automation, and data analysis using libraries like Pandas, NumPy, TensorFlow, Matplotlib, SciPy, and Scikit-Learn. At PythonGuides.com, he shares in-depth guides designed for both beginners and experienced developers. More about us.