livepython.net
CHAPTER 11While Loops
11.2  ENDLESS LOOPS

Infinite Loops in Python and How to Avoid Them

What Is an Infinite Loop?

An infinite loop (also called an endless loop) is a loop whose condition never becomes False, so it never stops on its own. It's the most famous while loop bug.

Here's one. Don't worry, this code is only shown, not run:

count = 1
while count <= 3:
    print("Hello")    # Hello, Hello, Hello ... forever

Spot the problem? Nothing inside the loop changes count. It's 1 at the first check, 1 at the second, and 1 at the millionth. 1 <= 3 stays True forever.

Think of a hamster wheel: the hamster runs and runs, but it never gets anywhere, because nothing ever changes.

What happens when you run one

  • In LivePython, code that runs too long is stopped for you: after a few seconds (2 in lesson editors, 5 on practice questions, 10 in the compiler), or when it prints far too much. The compiler and practice questions then show an error with a hint that points here.
  • On your own computer, the program keeps running. Press Ctrl + C in the terminal to stop it. Python then shows KeyboardInterrupt.

Neither one breaks your computer. An endless loop is a bug, not a disaster.

The fix

Make sure each round moves the variable toward making the condition False:

PYTHONedit me
count = 1
while count <= 3:
    print("Hello")
    count += 1
OUTPUT
Hello
Hello
Hello

Ask two questions

Before you run a while loop, ask yourself:

  1. Which variable does the condition check?
  2. Does a line inside the loop change it, in the right direction?

If either answer is "no", you've found an endless loop before it found you.

An infinite loop's condition never turns False. Something inside the loop must change it.

your turnPick the right idea

Will this loop ever stop?

n = 5 while n > 0: print(n)
Think about it, then pick one.
your turnType the output

Type what this prints

n = 3 while n > 0: n -= 1 print(n)
Read the code line by line, then type the output exactly.

Four Mistakes That Make a Loop Run Forever

Almost every infinite loop comes from one of four small mistakes. Learn them now, and you'll spot them before you press Run. All the broken examples here are only shown, never run.

Think of a road trip: you can never arrive if you don't drive, drive the wrong way, drive straight past the exit, or circle the car park.

1. No change

n = 1
while n <= 5:
    print(n)

Nothing changes n. Fix: add n += 1 inside the loop.

2. A change in the wrong direction

n = 5
while n > 0:
    print(n)
    n += 1

A countdown that counts up: 5, 6, 7… n > 0 stays True. Fix: n -= 1.

3. A check that jumps over its stop value

n = 1
while n != 10:
    n += 2

n goes 1, 3, 5, 7, 9, 11, 13… It never equals 10, so n != 10 is always True. Fix: use < instead of !=: while n < 10: stops at 11, whatever the step.

4. The change is outside the loop

n = 1
while n <= 3:
    print(n)
n += 1

n += 1 isn't indented, so it's after the loop, and Python never gets there. Fix: indent it by 4 spaces.

The checklist

CheckAsk yourself
ChangeDoes a line in the loop change the condition's variable?
DirectionDoes it move toward making the condition False?
Stop valueCould it jump past the value in a != check?
IndentationIs the change inside the block?

Most endless loops have no change, a backward change, a skipped stop value, or a change outside the block.

your turnPick the right idea

Will this loop stop?

n = 0 while n != 7: n += 2
Think about it, then pick one.
your turnPick the right idea

This countdown from 10 never ends. Which line has the bug?

n = 10 while n > 0: print(n) n += 1
Think about it, then pick one.

while True and break: Stop a Loop on Purpose

Sometimes an endless loop is exactly what you want, as long as it has a way out. while True: starts a loop that never stops by itself, and break (from chapter 10) jumps out of it the moment you decide.

PYTHONedit me
n = 1
while True:
    n *= 2
    if n > 50:
        break
    print(n)
print("Stopped at", n)
OUTPUT
2
4
8
16
32
Stopped at 64

True is always True, so the only way out is the break. When n becomes 64, the if runs break, and Python jumps straight to the first line after the loop. The print(n) below the break doesn't run for 64.

Think of a music player on repeat: the song plays again and again, until you press the stop button.

The rules

  • while True: loops forever, unless something stops it.
  • break ends the loop right away, even in the middle of the block.
  • Python sees a break only when it runs that line, so the if around it must become True at some point.
  • Every while True: needs a break you are sure will be reached.

When is it useful?

When the moment to stop is easiest to check in the middle of the round, not at the top. You'll use this a lot in the next topic, to stop when the user types a word like done.

Avoid: a break that can't happen

n = 1
while True:
    n += 2
    if n == 10:
        break

n is always odd (3, 5, 7, 9, 11…), so n == 10 is never True, and break never runs. Same mistake as a != check that skips its stop value. Use n > 10 instead.

while True needs a break that is sure to run.

your turnPredict the output

What will this print?

n = 0 while True: n += 3 if n > 7: break print(n)
Your turn! What will this code show on the screen?
your turnOrder the lines

Put the lines in order to print Round 1, then Round 2

  1. print("Round", count)
  2. if count == 2:
  3. break
  4. while True:
  5. count += 1
  6. count = 1
These lines are mixed up. Put them back in order, then press Check.

Off-by-One: One Round Too Many or Too Few

A loop that stops is not always right. An off-by-one error is a loop that runs one round too many or one too few. It's the second most common loop bug, after the endless loop, and Python gives no error for it.

PYTHONedit me
n = 1
while n < 5:
    print(n)
    n += 1
OUTPUT
1
2
3
4

The goal was 1 to 5, but 5 is missing. When n is 5, 5 < 5 is False, so 5 never gets its round. The fix is <=:

PYTHONedit me
n = 1
while n <= 5:
    print(n)
    n += 1
OUTPUT
1
2
3
4
5

Think of a fence: 5 metres of fence with a post every metre needs 6 posts, not 5. Counting the gaps or the posts is exactly where off-by-one mistakes hide.

Where it hides

ChoiceAsk yourself
< or <=Should the last value get a round?
start at 0 or 1What is the first value you want?
change before or after print()Should the first round print the start value?

The last row matters too. Move the change above the print(), and the output shifts by one:

PYTHONedit me
n = 1
while n <= 3:
    n += 1
    print(n)
OUTPUT
2
3
4

Test the edges

Check the first and the last value your loop prints, like testing the edges of an if in chapter 8. If both are right, the middle almost always is too.

Common beginner doubt: "How do I know how many rounds a loop runs?" With start 1, check <= 5 and step 1, it's 5 rounds. With < 5, it's 4. When in doubt, trace the first and last rounds on paper.

Check the first and last value: off-by-one bugs hide at the edges.

your turnFix the code

Make it print the numbers 1 to 5

It should print: 1 2 3 4 5

n = 1
while n < 5:
    print(n)
    n += 1
This code does not work yet. Fix it, then press Run.
your turnPredict the output

What will this print?

marks = 75 if marks >= 90: print("A") elif marks >= 70: print("B") else: print("C")
Your turn! What will this code show on the screen?

Practice: Endless loops

Solve these to lock in what you learned in this topic. Each one runs in your browser.

  1. 93.Fix the Endless Countdown LoopEasySolve
  2. 94.Python Program to Count the Weeks to Reach a Savings GoalMediumSolve