While Loops, break, and continue in Python
A clear guide to Python while loops — condition-driven iteration, break and continue, the else clause, infinite loops, and patterns for safe, terminating code.
What you'll learn
- ✓When to choose a while loop over a for loop
- ✓How break and continue change control flow
- ✓How to use the else clause on a while loop
- ✓How to write safe infinite loops with break
- ✓Common patterns: retry, polling, input validation
Prerequisites
- •Comfortable with for loops — see For Loops
- •Comfortable with conditionals — see Conditionals
A for loop is the right tool when you know what you are iterating over. A while loop is the right tool when you do not — when the number of iterations depends on a condition you check as you go. This post covers the while syntax, the control-flow keywords that pair with it, and the patterns where while is the natural choice.
The basic while loop
A while loop runs its body as long as a condition is true:
count = 0
while count < 5:
print(count)
count += 1
The condition is checked before each iteration. If it is false the first time, the body never runs at all:
n = 10
while n < 5:
print("never runs")
Three things must be true for a while loop to behave well:
- The condition is meaningful when the loop starts.
- Something in the body moves toward making the condition false.
- The exit condition is genuinely reachable.
Forgetting point two produces the most common bug with while: the infinite loop.
while vs for
Use for when the iteration count is known or comes from an iterable. Use while when continuation depends on a condition checked each pass — a value still being too large, a queue still being non-empty, a user still entering invalid input.
# for is awkward — we don't know how long this takes
import random
attempts = 0
while True:
attempts += 1
if random.random() < 0.1:
break
print(f"Took {attempts} attempts.")
If you find yourself faking for semantics with while (incrementing a counter, comparing against a length), reach for for and range instead.
break and continue
Both keywords change loop flow, and both work in while and for.
breakexits the loop immediately.continueskips the rest of the body and re-checks the condition.
# Read numbers until the user types "quit"
total = 0
while True:
raw = input("Number (or 'quit'): ")
if raw == "quit":
break
if not raw.strip().lstrip("-").isdigit():
print("Not a number, try again.")
continue
total += int(raw)
print("Total:", total)
The shape of this loop — while True with one or more break conditions inside — is a deliberate, idiomatic pattern, not laziness. It puts the exit conditions next to the code that detects them.
The while ... else clause
Like for, while has an optional else clause that runs when the loop ends without a break:
def has_factor(n, limit):
i = 2
while i < limit:
if n % i == 0:
print(f"{n} is divisible by {i}")
break
i += 1
else:
print(f"{n} has no small factors below {limit}")
has_factor(15, 10) # 15 is divisible by 3
has_factor(13, 10) # 13 has no small factors below 10
It is occasionally clarifying for search loops. Use sparingly and document when you do.
Infinite loops, intentional and otherwise
while True: is the explicit way to write a loop that runs until a break. This is appropriate when:
- The exit condition is easier to express in the body than in the header.
- There are multiple exit conditions.
- You are running an event loop, a server, or a polling worker.
while True:
job = queue.get()
if job is None:
break
process(job)
Unintentional infinite loops, by contrast, are usually a missing update:
# Bug: count never changes
count = 0
while count < 5:
print(count)
# forgot count += 1
If you hit one, interrupt with Ctrl+C. When debugging, print the loop variable on each iteration — it makes the missing update obvious.
Try it yourself. Write a guessing game. Pick a secret number with import random; secret = random.randint(1, 100). Loop with while True, read a guess with input, and break when the guess matches. Print “too high” or “too low” on each wrong guess, and count attempts.
Pattern: input validation
A common job for while is asking the user for input until they give something valid:
def ask_age():
while True:
raw = input("Enter your age: ")
if raw.isdigit():
age = int(raw)
if 0 < age < 130:
return age
print("Please enter a whole number between 1 and 129.")
Returning from inside the loop is clean. No flag variable, no second condition, no surprises. See Python Conditionals for more on the early-return style.
Pattern: retry with limit
When an operation may fail transiently, wrap it in a bounded retry:
import time
def fetch(url, retries=3, delay=1.0):
attempt = 0
while attempt < retries:
result = try_fetch(url)
if result is not None:
return result
attempt += 1
time.sleep(delay)
raise RuntimeError(f"Failed to fetch {url} after {retries} attempts.")
Always bound the number of retries. An unbounded retry loop becomes a denial-of-service against your own program.
Pattern: consume until empty
When working with a mutable queue or stack, while reads naturally:
stack = [1, 2, 3, 4, 5]
while stack:
top = stack.pop()
print(top)
# 5 4 3 2 1
while stack: uses the truthy/falsy rule covered in Conditionals — an empty list is falsy, so the loop exits when the stack is empty.
Pattern: convergence
Numerical algorithms often loop until a value stops changing meaningfully. Newton’s method for square roots, for example:
def sqrt(n, tol=1e-10):
if n < 0:
raise ValueError("n must be non-negative")
x = n if n >= 1 else 1.0
while abs(x * x - n) > tol:
x = (x + n / x) / 2
return x
print(sqrt(2)) # 1.4142135623730951
print(sqrt(100)) # 10.0
A tolerance — not exact equality — is the right exit condition. Floats rarely become exactly equal; see Comparison and Logical Operators for why.
Try it yourself. Write a function count_digits(n) that returns how many digits the non-negative integer n has. Use while n > 0: n //= 10 and a counter. Handle the special case n == 0 (which has one digit).
Nested loops and break
break only exits the innermost loop. To exit several at once, refactor into a function and use return:
def find(grid, target):
for r, row in enumerate(grid):
for c, value in enumerate(row):
if value == target:
return (r, c)
return None
print(find([[1, 2], [3, 4]], 3)) # (1, 0)
Trying to thread a flag variable through two nested loops is more code and less clear. Functions are the right tool.
A worked example
A small console “menu” loop that combines several patterns from this post:
def show_menu():
print()
print("1. Add task")
print("2. List tasks")
print("3. Remove task")
print("4. Quit")
def run():
tasks = []
while True:
show_menu()
choice = input("Choose: ").strip()
if choice == "1":
task = input("Task description: ").strip()
if not task:
print("Empty task ignored.")
continue
tasks.append(task)
elif choice == "2":
if not tasks:
print("No tasks yet.")
continue
for i, task in enumerate(tasks, start=1):
print(f" {i}. {task}")
elif choice == "3":
raw = input("Number to remove: ").strip()
if not raw.isdigit():
print("Not a number.")
continue
idx = int(raw) - 1
if 0 <= idx < len(tasks):
removed = tasks.pop(idx)
print(f"Removed: {removed}")
else:
print("Out of range.")
elif choice == "4":
print("Goodbye.")
break
else:
print("Unknown option.")
# run() # uncomment to run interactively
The outer while True loop runs until the user picks “Quit.” continue is used liberally to skip back to the menu after invalid input. Each branch is short because each one only handles its own case.
Recap
You now know:
whilechecks a condition before each iteration; the body must make progress toward exit- Use
whilewhen iteration depends on a condition, not a known sequence breakexits the loop;continueskips to the next checkwhile True: ... breakis an idiomatic pattern for multi-exit loopswhile ... elseruns if nobreakoccurred- Bound your retry loops; consume mutable containers with
while container: breakonly exits the innermost loop — usereturnto leave nested ones
Next steps
You now have the full toolkit for conditionals and loops. The next post moves to the other major dimension of structuring code: functions. We will cover def, return, arguments, and the habits that make functions worth reusing.
→ Next: Functions in Python — def, return, and Arguments
Questions or feedback? Email codeloomdevv@gmail.com.