Python While Loop — The Complete Guide
Syntax, while-else, break/continue/pass, infinite loops, nested loops, and exactly where a while loop beats a for loop — explained with real bugs, not textbook definitions.
Last Updated
July 2026
Read Time
28 min
Level
Beginner
What Is a While Loop in Python?
A while loop repeats a block of code for as long as a given condition stays True. That's the one-line definition. The part that actually matters in practice: unlike a for loop, which knows in advance how many times it's going to run because it's iterating over something with a known length, a while loop has no idea how many iterations it'll take. It just keeps checking the condition, over and over, until something inside the loop changes to make that condition false. That difference — known iteration count versus unknown — is the entire reason to pick one over the other, and most beginners never get told this explicitly.
Here's my honestly opinionated take, up front: a huge number of while loops I see in beginner code should actually be for loops, and a smaller but more dangerous number of for loops I see in intermediate code should actually be while loops. People reach for whichever one they learned first and force every problem into that shape. The real rule is simple — if you know the exact number of iterations ahead of time (a fixed range, a list, a file's lines), use for. If you're waiting for something to happen — a condition to flip, a sentinel value to show up, a retry to succeed — use while. Everything else in this guide is detail on top of that one decision.
count = 0
while count < 5:
print(f"Count is {count}")
count += 1
print("Loop finished")Output
Count is 0 Count is 1 Count is 2 Count is 3 Count is 4 Loop finishedHow a While Loop Actually Executes
Under the hood, a while loop does exactly three things, repeated in a cycle: evaluate the condition, run the body if it's True, jump back to re-evaluate the condition. That's it. There's no hidden counter, no implicit iterator, no magic. This is precisely why while loops give you the most control of any looping construct in Python — and also precisely why they're the easiest to get wrong. Nothing stops the condition from staying True forever except your own code inside the loop body actually changing something the condition depends on.
The condition itself doesn't have to be a comparison like count < 5. It can be any expression Python can evaluate as truthy or falsy — a boolean variable, a non-empty list, a function call that returns a boolean, even a complex expression combining several conditions with and/or. Python evaluates the whole expression fresh, every single time, before deciding whether to run the body again.
While Loop Execution Flow — Flowchart
The diagram below is the mental model to keep in your head every single time you write a while loop, especially when you're debugging one that won't stop, or one that never runs at all.
Code Execution Flow — from source to output
The step people miss most in that diagram: there is no automatic increment anywhere in this flow. A for loop over range(5) advances its counter for you, automatically, every cycle. A while loop does absolutely nothing to move itself forward — if you forget the line that updates whatever the condition depends on, the loop runs forever. That single missing line is, without exaggeration, the most common bug beginners write with while loops, and it's the reason this guide spends an entire section on infinite loops later.
The while-else Clause (The Most Misunderstood Feature in Python)
Python lets you attach an else block to a while loop, and I guarantee this is new information for a good chunk of people reading this, even people who've been writing Python for years. The else block runs only if the loop finished normally — meaning the condition eventually became False on its own, without a break statement cutting the loop short. If a break fires anywhere inside the loop body, the else block is skipped entirely.
numbers = [4, 8, 15, 16, 23, 42]
target = 99
i = 0
while i < len(numbers):
if numbers[i] == target:
print(f"Found {target} at index {i}")
break
i += 1
else:
print(f"{target} was not found in the list")
print("Search complete")Output
99 was not found in the list Search completeThis is genuinely the cleanest use case for while-else: a search loop where you need to distinguish between "found it, stopped early" and "looked through everything, never found it." Without else, you'd typically need a separate flag variable — something like found = False, set to True right before the break, then checked after the loop. The else clause removes that flag variable entirely. My honest take: I still think most developers, including experienced ones, avoid while-else because the naming is confusing — it reads like "else if the while loop is false," not "else if the loop never broke," and that mismatch between the keyword and its actual meaning causes more hesitation than the feature deserves. Learn it once, and it's genuinely useful in this exact search pattern.
break, continue, and pass — Loop Control Statements
Three keywords control the flow inside any loop body, and mixing them up is an easy mistake to make when you're moving fast.
- ▶
break — exits the loop immediately, skipping any remaining code in the body and skipping the else clause entirely. The loop stops as if the condition had just become False.
- ▶
continue — skips the rest of the current iteration's body and jumps straight back to re-checking the loop condition. The loop keeps running; it just doesn't finish executing the current pass through the body.
- ▶
pass — does literally nothing. It's a no-op placeholder, used when Python's syntax requires an indented block but you don't have any code to put there yet.
n = 0
while n < 10:
n += 1
if n == 3:
continue # skip printing 3, but keep looping
if n == 7:
break # stop the loop entirely once n hits 7
if n == 5:
pass # placeholder, does nothing special here
print(n)
print("Done")Output
1 2 4 5 6 DoneThe continue Trap — Forgetting the Increment
This is a real bug, and it's specific to while loops in a way it isn't for for loops. If your increment statement (n += 1) sits AFTER a continue check but the increment is what triggers the condition that leads to continue, you can accidentally skip the increment and freeze the loop forever. The fix, as shown above, is to put the increment as the very first thing in the loop body, before any conditional logic that might continue. Get this order backwards and you'll be staring at a script that's just hanging, no error, no output, no obvious clue why — until you notice the counter variable never actually changes.
# BUGGY VERSION — this hangs forever
n = 0
while n < 5:
if n == 2:
continue # jumps back WITHOUT reaching n += 1 below
print(n)
n += 1 # never reached when n == 2, loop freezes at n=2 foreverInfinite Loops — Intentional vs Accidental
An infinite loop is any loop whose condition never becomes False. Sometimes that's exactly what you want. Most of the time, when a beginner hits one, it's a bug, and it's usually one of two causes: either the variable the condition depends on never actually gets updated inside the loop body, or the update happens but never moves the condition toward becoming false (incrementing in the wrong direction, comparing against the wrong value, or updating a different variable than the one the condition checks).
Intentional Infinite Loops — while True:
The while True: pattern is one of the most common idioms in real Python code, and it's completely legitimate. Web servers, chat bots, game loops, and command-line tools that keep prompting for input all rely on a loop that runs forever by design, exiting only through an explicit break somewhere inside based on real logic — not through the condition itself ever going false.
while True:
user_input = input("Enter a command ('quit' to exit): ")
if user_input.lower() == "quit":
print("Goodbye!")
break
print(f"You typed: {user_input}")This pattern is arguably clearer than trying to cram the exit condition into the while line itself, especially when the actual exit logic needs to run some code first (like printing "Goodbye!") before actually leaving. It's the same idea we saw earlier with the walrus operator solving the "read input, then check it" problem — while True plus an internal break is the more general, more flexible version of that same pattern.
Accidental Infinite Loops — The Real Debugging Scenario
Here's a genuinely common accidental version. Someone's building a retry loop for a flaky API call, and they write the retry counter update inside an if block that only runs on success — meaning on every failure, the counter never advances, and the loop just keeps hammering the same failing request indefinitely, forever, until someone notices the process is stuck and has to Ctrl+C it in the terminal (or worse, notices it in a production log an hour later, after it's already burned through a rate limit or run up a cloud bill).
# BUGGY — attempts never increments on failure, loops forever
attempts = 0
max_attempts = 5
success = False
while attempts < max_attempts and not success:
result = call_flaky_api() # imagine this sometimes fails
if result.ok:
success = True
attempts += 1 # BUG: only increments on success
# FIXED — attempts increments regardless of outcome
attempts = 0
while attempts < max_attempts and not success:
result = call_flaky_api()
attempts += 1 # always runs, guarantees the loop terminates
if result.ok:
success = TrueThe fix is a one-line move — pull the increment out of the conditional block and make it unconditional. The general lesson: whatever variable your while condition checks, make sure the thing that updates it runs on every single pass through the loop, not just the happy path. If you catch yourself writing an increment inside an if block, stop and ask whether the loop can still terminate on the branch where that if doesn't fire.
How to Actually Kill a Runaway Loop
If you've run a script and it's just sitting there, not responding, not printing anything, that's almost always an infinite loop. In a terminal, Ctrl+C sends a KeyboardInterrupt which will stop most stuck Python scripts immediately. In a Jupyter Notebook, use the Kernel → Interrupt option, or the stop (square) button, since Ctrl+C in a notebook cell usually doesn't do what you expect. If neither works because the loop is stuck inside a C extension call that doesn't check for interrupts, you may genuinely need to kill the process from your OS's task manager or with kill -9 <pid> on Linux/macOS.
Nested While Loops
You can put a while loop inside another while loop, same as with for loops. The inner loop runs to completion on every single pass of the outer loop. This is genuinely useful for grid-based logic, matrix traversal, or any two-dimensional problem, but it comes with a real performance warning: if the outer loop runs n times and the inner loop runs m times on each pass, your total work is n * m, not n + m. That difference is easy to underestimate until you're staring at a script that's technically correct but takes eleven minutes to process what should've taken two seconds.
row = 1
while row <= 3:
col = 1
while col <= 3:
print(f"({row},{col})", end=" ")
col += 1
print() # newline after each row
row += 1Output
(1,1) (1,2) (1,3) (2,1) (2,2) (2,3) (3,1) (3,2) (3,3)break Only Exits the Innermost Loop
This is another real gotcha. A break inside a nested loop only exits the loop it's directly written inside — it does NOT jump out of both loops at once, even though a lot of people intuitively expect it to. If you need to break out of two or more nested loops simultaneously, you generally need either a flag variable checked in the outer loop's condition, or you wrap the whole thing in a function and use return to exit everything at once, which is honestly the cleaner option in most real code.
found = False
row = 0
while row < 3 and not found:
col = 0
while col < 3:
if row == 1 and col == 1:
found = True
break # only exits the INNER while loop
col += 1
row += 1
print(f"Match found: {found}, stopped at row={row}")Output
Match found: True, stopped at row=2While Loop vs For Loop — When to Use Which
This decision comes up constantly, and getting it wrong doesn't usually crash your program — it just makes the code harder to read and occasionally introduces the exact infinite-loop bugs covered above.
The short version, if you only remember one sentence from this whole section: for loops iterate over something, while loops wait for something. If you find yourself writing i = 0 before a while loop and i += 1 inside it just to count up to a fixed number, stop — that's a for i in range(n): wearing a disguise, and the for-loop version is both shorter and structurally incapable of becoming an infinite loop by accident.
Try It Yourself — While Loop Playground
Edit the snippet below. Try changing the condition, removing the increment (carefully — you'll need to stop the runtime if it hangs), or adding a break partway through.
balance = 1000
withdrawal = 150
while balance >= withdrawal:
balance -= withdrawal
print(f"Withdrew {withdrawal}, remaining balance: {balance}")
print(f"Final balance: {balance} (not enough left for another withdrawal)")Output
Withdrew 150, remaining balance: 850 Withdrew 150, remaining balance: 700 Withdrew 150, remaining balance: 550 Withdrew 150, remaining balance: 400 Withdrew 150, remaining balance: 250 Withdrew 150, remaining balance: 100 Final balance: 100 (not enough left for another withdrawal)Practice This Code — Live Editor
Where While Loops Actually Show Up in Real Code
- ▶
Retry logic for network calls — while attempts < max_retries and not success: is the standard shape for calling a flaky API or a database connection that might briefly be unavailable.
- ▶
Reading from a stream until it's exhausted — while chunk := file.read(1024): reads a file in fixed-size chunks until nothing's left, combining the walrus operator with a while loop for a clean one-liner.
- ▶
Game loops — while game_running: is the literal backbone of nearly every game built with Pygame or similar libraries, running every frame until the player quits.
- ▶
Command-line REPLs and interactive tools — while True: prompting for input and breaking on an exit command is the standard pattern for any interactive CLI tool.
- ▶
Polling for a background job to finish — while not job.is_complete(): time.sleep(2) is common in scripts checking on a long-running cloud task, a Celery worker, or a batch processing job.
- ▶
Binary search and other unknown-iteration-count algorithms — algorithms like binary search naturally use while low <= high: because the exact number of iterations depends on the data, not a fixed range.
- ▶
Server main loops — a basic socket server's core loop (while True: conn, addr = server.accept()) that keeps accepting new connections indefinitely.
Do's and Don'ts With While Loops
Python While Loop — Interview Questions
Practice Questions — Test Your Understanding
1. What does this loop print? i = 0; while i < 3: print(i); i += 1
Easy2. Why does this loop never terminate? x = 10; while x > 0: print(x); x += 1
Easy3. What's the output of: n = 5; while n > 0: n -= 1; if n == 2: continue; print(n)
Medium4. Does the else block run in this code? i = 0; while i < 3: i += 1; if i == 2: break; else: print('done')
Medium5. What happens if you write while [1, 2, 3]: instead of a boolean condition?
Medium6. In nested while loops, does a single break in the inner loop stop the outer loop too?
Medium7. Rewrite this while loop as a for loop: i = 0; total = 0; while i < 10: total += i; i += 1
Hard8. Why might while chunk := file.read(1024): be preferred over a manual while True with a break for reading a file?
HardConclusion — Mastering the While Loop
The while loop is the simplest looping construct in Python to describe and, honestly, one of the easiest to get subtly wrong. There's no safety net — no automatic iterator managing termination for you the way a for loop has. That's exactly what makes it powerful for the situations where you genuinely don't know how many iterations you need, and exactly what makes it dangerous when you use it for situations where you do.
If there's one habit worth carrying forward from this entire guide, it's this: every time you write a while loop, before you move on, trace through in your head exactly which line updates the condition, and confirm that line runs on every single pass, not just the happy path. That one check catches the overwhelming majority of infinite-loop bugs before they ever reach production, a code review, or an on-call page at 2am.
Next, pair this with a solid grip on Python's for loop and comprehensions — once both looping constructs are second nature, choosing between them stops being a conscious decision and starts being an instinct, which is exactly where you want to be as a developer working on real, unpredictable codebases.